home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / PARSTXTR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-15  |  76.6 KB  |  3,311 lines  |  [TEXT/CWIE]

  1. /****************************************************************************
  2. *                parstxtr.c
  3. *
  4. *  This module parses textures and atmosphere effects.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "parse.h"
  28. #include "parstxtr.h"
  29. #include "colour.h"
  30. #include "express.h"
  31. #include "gif.h"
  32. #include "halos.h"
  33. #include "iff.h"
  34. #include "image.h"
  35. #include "matrices.h" 
  36. #include "normal.h"   
  37. #include "pigment.h"  
  38. #include "povray.h"
  39. #include "pgm.h"
  40. #include "ppm.h"
  41. #include "targa.h"
  42. #include "png_pov.h"
  43. #include "texture.h"
  44. #include "tokenize.h"
  45.  
  46.  
  47. /*****************************************************************************
  48. * Local preprocessor defines
  49. ******************************************************************************/
  50.  
  51. #define ADD_TNORMAL if (Tnormal == NULL) {if ((Default_Texture->Tnormal) != NULL) \
  52.  Tnormal = Copy_Tnormal ((Default_Texture->Tnormal)); else Tnormal = Create_Tnormal ();\
  53.  Texture->Tnormal=Tnormal;};
  54.  
  55. /*****************************************************************************
  56. * Local typedefs
  57. ******************************************************************************/
  58.  
  59.  
  60.  
  61. /*****************************************************************************
  62. * Local variables
  63. ******************************************************************************/
  64.  
  65. TEXTURE *Default_Texture;
  66.  
  67.  
  68.  
  69. /*****************************************************************************
  70. * Static functions
  71. ******************************************************************************/
  72.  
  73. static void Parse_Bump_Map PARAMS((TNORMAL *Tnormal));
  74. static void Parse_Image_Map PARAMS((PIGMENT *Pigment));
  75. static void Parse_Pattern PARAMS((TPATTERN *New, int TPat_Type));
  76. static TEXTURE *Parse_Vers1_Texture PARAMS((void));
  77. static TEXTURE *Parse_Tiles PARAMS((void));
  78. static TEXTURE *Parse_Material_Map PARAMS((void));
  79. static void Parse_Texture_Transform PARAMS((TEXTURE *Texture));
  80. static TURB *Check_Turb PARAMS((WARP **Warps_Ptr));
  81. static void Parse_Warp PARAMS((WARP **Warp_Ptr));
  82. static void Check_BH_Parameters PARAMS((BLACK_HOLE *bh));
  83.  
  84.  
  85.  
  86. /*****************************************************************************
  87. *
  88. * FUNCTION
  89. *
  90. * INPUT
  91. *
  92. * OUTPUT
  93. *
  94. * RETURNS
  95. *
  96. * AUTHOR
  97. *
  98. *   POV-Ray Team
  99. *   
  100. * DESCRIPTION
  101. *
  102. * CHANGES
  103. *
  104. ******************************************************************************/
  105.  
  106. IMAGE *Parse_Image (Legal)
  107.   int Legal;
  108.   {
  109.    IMAGE *Image;
  110.    VECTOR Local_Vector;
  111.    char *Name;
  112.  
  113.    Image = Create_Image ();
  114.  
  115.    Image->Image_Type = Legal;
  116.  
  117.    if (Legal & GRAD_FILE)
  118.      {
  119.       EXPECT
  120.         CASE_VECTOR
  121.           Warn(1.5, "Should use map_type keyword and/or eliminate orientation.");
  122.           Have_Vector = FALSE;
  123.           Parse_Vector_Float (Local_Vector);
  124.           if (Have_Vector)
  125.             Assign_Vector(Image->Gradient,Local_Vector);
  126.           else
  127.             Image->Map_Type = (int)Local_Vector[X];
  128.         END_CASE
  129.  
  130.         OTHERWISE
  131.           UNGET
  132.           EXIT
  133.         END_CASE
  134.       END_EXPECT
  135.      }
  136.  
  137.    EXPECT
  138.      CASE (IFF_TOKEN)
  139.        Image->File_Type = IFF_FILE;
  140.        Name=Parse_String();
  141.        Read_Iff_Image (Image, Name);
  142.        POV_FREE(Name);
  143.        EXIT
  144.      END_CASE
  145.  
  146.      CASE (GIF_TOKEN)
  147.        Image->File_Type = GIF_FILE;
  148.        Name=Parse_String();
  149.        Read_Gif_Image(Image, Name);
  150.        POV_FREE(Name);
  151.        EXIT
  152.      END_CASE
  153.  
  154.      CASE (POT_TOKEN)
  155.        Image->File_Type = POT_FILE;
  156.        Name=Parse_String();
  157.        Read_Gif_Image(Image, Name);
  158.        POV_FREE(Name);
  159.        EXIT
  160.      END_CASE
  161.  
  162.      CASE (SYS_TOKEN)
  163.        Image->File_Type = SYS_FILE;
  164.        Name=Parse_String();
  165.        READ_SYS_IMAGE(Image, Name);
  166.        POV_FREE(Name);
  167.        EXIT
  168.      END_CASE
  169.  
  170.      CASE (TGA_TOKEN)
  171.        Image->File_Type = TGA_FILE;
  172.        Name=Parse_String();
  173.        Read_Targa_Image(Image, Name);
  174.        POV_FREE(Name);
  175.        EXIT
  176.      END_CASE
  177.  
  178.      CASE (PNG_TOKEN)
  179.        Image->File_Type = PNG_FILE;
  180.        Name=Parse_String();
  181.        Read_Png_Image(Image, Name);
  182.        POV_FREE(Name);
  183.        EXIT
  184.      END_CASE
  185.  
  186.      CASE (PGM_TOKEN)
  187.        Image->File_Type = PGM_FILE;
  188.        Name=Parse_String();
  189.        Read_PGM_Image(Image, Name);
  190.        POV_FREE(Name);
  191.        EXIT
  192.      END_CASE
  193.  
  194.      CASE (PPM_TOKEN)
  195.        Image->File_Type = PPM_FILE;
  196.        Name=Parse_String();
  197.        Read_PPM_Image(Image, Name);
  198.        POV_FREE(Name);
  199.        EXIT
  200.      END_CASE
  201.  
  202.      OTHERWISE
  203.        Parse_Error_Str ("map file spec");
  204.      END_CASE
  205.    END_EXPECT
  206.  
  207.    if (!(Image->File_Type & Legal))
  208.      Error ("File type not supported here.");
  209.    return (Image);
  210.   }
  211.  
  212.  
  213.  
  214. /*****************************************************************************
  215. *
  216. * FUNCTION
  217. *
  218. * INPUT
  219. *
  220. * OUTPUT
  221. *
  222. * RETURNS
  223. *
  224. * AUTHOR
  225. *
  226. *   POV-Ray Team
  227. *   
  228. * DESCRIPTION
  229. *
  230. * CHANGES
  231. *
  232. ******************************************************************************/
  233.  
  234. static void Parse_Image_Map (Pigment)
  235. PIGMENT *Pigment;
  236.   {
  237.    int reg;
  238.    IMAGE *Image;
  239.    
  240.    Parse_Begin();
  241.  
  242.    Image = Parse_Image (IMAGE_FILE);
  243.    Image->Use_Colour_Flag = TRUE;
  244.  
  245.    EXPECT                   /* Look for image_attribs */
  246.      CASE (ONCE_TOKEN)
  247.        Image->Once_Flag=TRUE;
  248.      END_CASE
  249.  
  250.      CASE (INTERPOLATE_TOKEN)
  251.        Image->Interpolation_Type = (int)Parse_Float();
  252.      END_CASE
  253.  
  254.      CASE (MAP_TYPE_TOKEN)
  255.        Image->Map_Type = (int) Parse_Float ();
  256.      END_CASE
  257.  
  258.      CASE (USE_COLOUR_TOKEN)
  259.        Image->Use_Colour_Flag = TRUE;
  260.      END_CASE
  261.  
  262.      CASE (USE_INDEX_TOKEN)
  263.        Image->Use_Colour_Flag = FALSE;
  264.      END_CASE
  265.  
  266.      CASE (ALPHA_TOKEN)
  267.        Warn(1.55, "Keyword ALPHA discontinued. Use FILTER instead.");
  268.  
  269.      CASE (COLOUR_KEY_TOKEN)
  270.        switch(Token.Function_Id)
  271.          {
  272.           case FILTER_TOKEN:
  273.             EXPECT
  274.               CASE (ALL_TOKEN)
  275.                 {
  276.                  DBL filter;
  277.                  filter = Parse_Float();
  278.                  for (reg = 0 ; reg < Image->Colour_Map_Size ; reg++)
  279.                    Image->Colour_Map[reg].Filter
  280.                        = (unsigned short) (filter *255.0);
  281.                 }
  282.                 EXIT
  283.               END_CASE
  284.  
  285.               OTHERWISE
  286.                 UNGET
  287.                 reg = (int)(Parse_Float() + 0.01);
  288.                 if (Image->Colour_Map == NULL)
  289.                   Not_With ("filter","non color-mapped image");
  290.                 if ((reg < 0) || (reg >= Image->Colour_Map_Size))
  291.                   Error ("FILTER color register value out of range.");
  292.  
  293.                 Parse_Comma();
  294.                 Image->Colour_Map[reg].Filter
  295.                        = (unsigned short) (255.0 * Parse_Float());
  296.                 EXIT
  297.               END_CASE
  298.  
  299.             END_EXPECT
  300.             Pigment->Flags |= HAS_FILTER;
  301.             break;
  302.  
  303.           case TRANSMIT_TOKEN:
  304.             EXPECT
  305.               CASE (ALL_TOKEN)
  306.                 {
  307.                  DBL transmit;
  308.                  transmit = Parse_Float();
  309.                  for (reg = 0 ; reg < Image->Colour_Map_Size ; reg++)
  310.                    Image->Colour_Map[reg].Transmit
  311.                        = (unsigned short) (transmit *255.0);
  312.                 }
  313.                 EXIT
  314.               END_CASE
  315.  
  316.               OTHERWISE
  317.                 UNGET
  318.                 reg = (int)(Parse_Float() + 0.01);
  319.                 if (Image->Colour_Map == NULL)
  320.                   Not_With ("transmit","non color-mapped image");
  321.                 if ((reg < 0) || (reg >= Image->Colour_Map_Size))
  322.                   Error ("TRANSMIT color register value out of range.");
  323.  
  324.                 Parse_Comma();
  325.                 Image->Colour_Map[reg].Transmit
  326.                        = (unsigned short) (255.0 * Parse_Float());
  327.                 EXIT
  328.               END_CASE
  329.  
  330.             END_EXPECT
  331.             Pigment->Flags |= HAS_FILTER;
  332.             break;
  333.  
  334.           default:
  335.             UNGET
  336.             Parse_Error_Str ("filter or transmit");
  337.             break;
  338.          }
  339.      END_CASE
  340.  
  341.      OTHERWISE
  342.        UNGET
  343.        EXIT
  344.      END_CASE
  345.    END_EXPECT
  346.    
  347.    Pigment->Vals.Image=Image;
  348.    Parse_End();
  349. }
  350.  
  351.  
  352.  
  353. /*****************************************************************************
  354. *
  355. * FUNCTION
  356. *
  357. * INPUT
  358. *
  359. * OUTPUT
  360. *
  361. * RETURNS
  362. *
  363. * AUTHOR
  364. *
  365. *   POV-Ray Team
  366. *   
  367. * DESCRIPTION
  368. *
  369. * CHANGES
  370. *
  371. ******************************************************************************/
  372.  
  373. static void Parse_Bump_Map (Tnormal)
  374. TNORMAL *Tnormal;
  375.   {
  376.    IMAGE *Image;
  377.  
  378.    Parse_Begin();
  379.  
  380.    Image = Parse_Image(IMAGE_FILE);
  381.    Image->Use_Colour_Flag = TRUE;
  382.  
  383.    EXPECT
  384.      CASE (ONCE_TOKEN)
  385.        Image->Once_Flag=TRUE;
  386.      END_CASE
  387.  
  388.      CASE (MAP_TYPE_TOKEN)
  389.        Image->Map_Type = (int) Parse_Float ();
  390.      END_CASE
  391.  
  392.      CASE (INTERPOLATE_TOKEN)
  393.        Image->Interpolation_Type = (int)Parse_Float();
  394.      END_CASE
  395.  
  396.      CASE (BUMP_SIZE_TOKEN)
  397.        Tnormal->Amount = Parse_Float ();
  398.      END_CASE
  399.  
  400.      CASE (USE_COLOUR_TOKEN)
  401.        Image->Use_Colour_Flag = TRUE;
  402.      END_CASE
  403.  
  404.      CASE (USE_INDEX_TOKEN)
  405.        Image->Use_Colour_Flag = FALSE;
  406.      END_CASE
  407.  
  408.      OTHERWISE
  409.        UNGET
  410.        EXIT
  411.      END_CASE
  412.    END_EXPECT
  413.  
  414.    Tnormal->Vals.Image=Image;
  415.  
  416.    Parse_End();
  417. }
  418.  
  419.  
  420.  
  421. /*****************************************************************************
  422. *
  423. * FUNCTION
  424. *
  425. * INPUT
  426. *
  427. * OUTPUT
  428. *
  429. * RETURNS
  430. *
  431. * AUTHOR
  432. *
  433. *   POV-Ray Team
  434. *
  435. * DESCRIPTION
  436. *
  437. * CHANGES
  438. *
  439. ******************************************************************************/
  440.  
  441. void Parse_Pigment (Pigment_Ptr)
  442.   PIGMENT **Pigment_Ptr;
  443.   {
  444.    EXPECT            /* Look for [pigment_id] */
  445.      CASE (PIGMENT_ID_TOKEN)
  446.        Destroy_Pigment(*Pigment_Ptr);
  447.        *Pigment_Ptr = Copy_Pigment ((PIGMENT *) Token.Constant_Data);
  448.        EXIT
  449.      END_CASE
  450.  
  451.      OTHERWISE
  452.        UNGET
  453.        EXIT
  454.      END_CASE
  455.    END_EXPECT    /* End pigment_id */
  456.    
  457.    Parse_Pattern((TPATTERN *)(*Pigment_Ptr),PIGMENT_TYPE);
  458.  
  459.    if (Not_In_Default && ((*Pigment_Ptr)->Type == NO_PATTERN))
  460.    {
  461.      Warn(1.7, "Pigment type unspecified or not 1st item.");
  462.    }
  463.   }
  464.  
  465.  
  466.  
  467. /*****************************************************************************
  468. *
  469. * FUNCTION
  470. *
  471. * INPUT
  472. *
  473. * OUTPUT
  474. *
  475. * RETURNS
  476. *
  477. * AUTHOR
  478. *
  479. *   POV-Ray Team
  480. *
  481. * DESCRIPTION
  482. *
  483. * CHANGES
  484. *
  485. ******************************************************************************/
  486.  
  487. static void Parse_Pattern (New, TPat_Type)
  488.   TPATTERN *New;
  489.   int TPat_Type;
  490.   {
  491.    VECTOR Local_Vector;
  492.    COLOUR Local_Colour;
  493.    MATRIX Local_Matrix;
  494.    TRANSFORM Local_Trans;
  495.    TURB *Local_Turb;
  496.    unsigned short Old_Type=New->Type;
  497.    IMAGE *Old_Image = NULL;
  498.  
  499.    if (Old_Type==BITMAP_PATTERN)
  500.    {
  501.      Old_Image=New->Vals.Image;
  502.    }
  503.  
  504.    EXPECT
  505.      CASE (AGATE_TOKEN)
  506.        New->Type = AGATE_PATTERN;
  507.        Check_Turb(&(New->Warps));
  508.        New->Vals.Agate_Turb_Scale = 1.0;
  509.        EXIT
  510.      END_CASE
  511.  
  512.      CASE (BOZO_TOKEN)
  513.        New->Type = BOZO_PATTERN;
  514.        EXIT
  515.      END_CASE
  516.  
  517.      CASE (GRANITE_TOKEN)
  518.        New->Type = GRANITE_PATTERN;
  519.        EXIT
  520.      END_CASE
  521.  
  522.      CASE (LEOPARD_TOKEN)
  523.        New->Type = LEOPARD_PATTERN;
  524.        EXIT
  525.      END_CASE
  526.  
  527.      CASE (MARBLE_TOKEN)
  528.        New->Type = MARBLE_PATTERN;
  529.        New->Wave_Type = TRIANGLE_WAVE;
  530.        EXIT
  531.      END_CASE
  532.  
  533.      CASE (MANDEL_TOKEN)
  534.        New->Type = MANDEL_PATTERN;
  535.        New->Vals.Iterations = (int)Parse_Float();
  536.        EXIT
  537.      END_CASE
  538.  
  539.      CASE (ONION_TOKEN)
  540.        New->Type = ONION_PATTERN;
  541.        EXIT
  542.      END_CASE
  543.  
  544.      CASE (PATTERN1_TOKEN)
  545.        New->Type = PATTERN1_PATTERN;
  546.        EXIT
  547.      END_CASE
  548.  
  549.      CASE (PATTERN2_TOKEN)
  550.        New->Type = PATTERN2_PATTERN;
  551.        EXIT
  552.      END_CASE
  553.  
  554.      CASE (PATTERN3_TOKEN)
  555.        New->Type = PATTERN3_PATTERN;
  556.        EXIT
  557.      END_CASE
  558.  
  559.      CASE (BUMPY1_TOKEN)
  560.        if (TPat_Type != NORMAL_TYPE)
  561.        {
  562.          Only_In("bumpy1","normal");
  563.        }
  564.        New->Type = BUMPY1_PATTERN;
  565.        EXIT
  566.      END_CASE
  567.  
  568.      CASE (BUMPY2_TOKEN)
  569.        if (TPat_Type != NORMAL_TYPE)
  570.        {
  571.          Only_In("bumpy2","normal");
  572.        }
  573.        New->Type = BUMPY2_PATTERN;
  574.        EXIT
  575.      END_CASE
  576.  
  577.      CASE (BUMPY3_TOKEN)
  578.        if (TPat_Type != NORMAL_TYPE)
  579.        {
  580.          Only_In("bumpy3","normal");
  581.        }
  582.        New->Type = BUMPY3_PATTERN;
  583.        EXIT
  584.      END_CASE
  585.  
  586.      CASE (SPIRAL1_TOKEN)
  587.        New->Type = SPIRAL1_PATTERN;
  588.        New->Vals.Arms = (short)Parse_Float ();
  589.        New->Wave_Type = TRIANGLE_WAVE;
  590.        EXIT
  591.      END_CASE
  592.  
  593.      CASE (SPIRAL2_TOKEN)
  594.        New->Type = SPIRAL2_PATTERN;
  595.        New->Vals.Arms = (short)Parse_Float ();
  596.        New->Wave_Type = TRIANGLE_WAVE;
  597.        EXIT
  598.      END_CASE
  599.  
  600.      CASE (SPOTTED_TOKEN)
  601.        New->Type = SPOTTED_PATTERN;
  602.        EXIT
  603.      END_CASE
  604.  
  605.      CASE (WOOD_TOKEN)
  606.        New->Type = WOOD_PATTERN;
  607.        New->Wave_Type = TRIANGLE_WAVE;
  608.        EXIT
  609.      END_CASE
  610.  
  611.      CASE (GRADIENT_TOKEN)
  612.        New->Type = GRADIENT_PATTERN;
  613.        Parse_Vector (New->Vals.Gradient);
  614.        EXIT
  615.      END_CASE
  616.  
  617.      CASE (RADIAL_TOKEN)
  618.        New->Type = RADIAL_PATTERN;
  619.        EXIT
  620.      END_CASE
  621.  
  622.      CASE (CRACKLE_TOKEN)
  623.        New->Type = CRACKLE_PATTERN;
  624.        EXIT
  625.      END_CASE
  626.  
  627.      CASE_COLOUR
  628.        if (TPat_Type != PIGMENT_TYPE)
  629.        {
  630.          Only_In("color","pigment");
  631.        }
  632.        New->Type = PLAIN_PATTERN;
  633.        Parse_Colour (((PIGMENT *)New)->Colour);
  634.        EXIT
  635.      END_CASE
  636.  
  637.      CASE (CHECKER_TOKEN)
  638.        New->Type = CHECKER_PATTERN;
  639.        New->Frequency = 0.0;
  640.        Destroy_Blend_Map(New->Blend_Map);
  641.        New->Blend_Map = Parse_Blend_List(2,&Check_Default_Map,TPat_Type);
  642.        EXIT
  643.      END_CASE
  644.  
  645.      CASE (BRICK_TOKEN)
  646.        if (New->Type!=BRICK_PATTERN)
  647.        {
  648.          Make_Vector(New->Vals.Brick.Size,8.0,3.0,4.5);
  649.          New->Vals.Brick.Mortar=0.5-Small_Tolerance*2.0;
  650.        New->Type = BRICK_PATTERN;
  651.        }
  652.        New->Frequency = 0.0;
  653.        Destroy_Blend_Map(New->Blend_Map);
  654.        New->Blend_Map = Parse_Blend_List(2,&Brick_Default_Map,TPat_Type);
  655.        EXIT
  656.      END_CASE
  657.  
  658.      CASE (HEXAGON_TOKEN)
  659.        New->Type = HEXAGON_PATTERN;
  660.        New->Frequency = 0.0;
  661.        Destroy_Blend_Map(New->Blend_Map);
  662.        New->Blend_Map = Parse_Blend_List(3,&Hex_Default_Map,TPat_Type);
  663.        EXIT
  664.      END_CASE
  665.  
  666.      CASE (IMAGE_MAP_TOKEN)
  667.        if (TPat_Type != PIGMENT_TYPE)
  668.        {
  669.          Only_In("image_map","pigment");
  670.        }
  671.  
  672.        if (Old_Type==BITMAP_PATTERN) 
  673.        {
  674.          Destroy_Image(Old_Image);
  675.        }   
  676.  
  677.        New->Type = BITMAP_PATTERN;
  678.        New->Frequency = 0.0;
  679.        Parse_Image_Map ((PIGMENT *)New);
  680.        EXIT
  681.      END_CASE
  682.  
  683.      CASE (BUMP_MAP_TOKEN)
  684.        if (TPat_Type != NORMAL_TYPE)
  685.        {
  686.          Only_In("bump_map","normal");
  687.        }
  688.  
  689.        if (Old_Type==BITMAP_PATTERN) 
  690.        {
  691.          Destroy_Image(Old_Image);
  692.        }   
  693.  
  694.        New->Type = BITMAP_PATTERN;
  695.        New->Frequency = 0.0;
  696.        Parse_Bump_Map ((TNORMAL *)New);
  697.        EXIT
  698.      END_CASE
  699.  
  700.      CASE (WAVES_TOKEN)
  701.        New->Type = WAVES_PATTERN;
  702.        EXIT
  703.      END_CASE
  704.  
  705.      CASE (RIPPLES_TOKEN)
  706.        New->Type = RIPPLES_PATTERN;
  707.        EXIT
  708.      END_CASE
  709.  
  710.      CASE (WRINKLES_TOKEN)
  711.        New->Type = WRINKLES_PATTERN;
  712.        EXIT
  713.      END_CASE
  714.  
  715.      CASE (BUMPS_TOKEN)
  716.        New->Type = BUMPS_PATTERN;
  717.        EXIT
  718.      END_CASE
  719.  
  720.      CASE (DENTS_TOKEN)
  721.        New->Type = DENTS_PATTERN;
  722.        EXIT
  723.      END_CASE
  724.  
  725.      CASE (QUILTED_TOKEN)
  726.        New->Type = QUILTED_PATTERN;
  727.        New->Vals.Quilted.Control0 = 1.0;
  728.        New->Vals.Quilted.Control1 = 1.0;
  729.        New->Frequency = 0.0;
  730.        EXIT
  731.      END_CASE
  732.  
  733.      CASE (AVERAGE_TOKEN)
  734.        New->Type = AVERAGE_PATTERN;
  735.        EXIT
  736.      END_CASE
  737.  
  738.      OTHERWISE
  739.        UNGET
  740.        EXIT
  741.      END_CASE
  742.    END_EXPECT     /* Concludes pattern_body */
  743.  
  744.    if ((Old_Type==BITMAP_PATTERN) && (New->Type!=BITMAP_PATTERN))
  745.    {
  746.      Destroy_Image(Old_Image);
  747.    }   
  748.  
  749.    if (TPat_Type == NORMAL_TYPE) 
  750.     {
  751.      Parse_Comma();
  752.      ((TNORMAL *)New)->Amount = Allow_Float (((TNORMAL *)New)->Amount );
  753.     }
  754.  
  755.    EXPECT         /* Look for pattern_modifier */
  756.      CASE (TURBULENCE_TOKEN)
  757.        Local_Turb=Check_Turb(&(New->Warps));
  758.        Parse_Vector_Float(Local_Turb->Turbulence);
  759.      END_CASE
  760.  
  761.      CASE (COLOUR_MAP_TOKEN)
  762.        if (TPat_Type != PIGMENT_TYPE)
  763.        {
  764.          Only_In("color_map","pigment");
  765.        }
  766.        if (New->Type == CHECKER_PATTERN ||
  767.            New->Type == BRICK_PATTERN ||
  768.            New->Type == HEXAGON_PATTERN ||
  769.            New->Type == PLAIN_PATTERN ||
  770.            New->Type == BITMAP_PATTERN)
  771.          Warn(1.5, "Cannot use color map with this pigment type.");
  772.        Destroy_Blend_Map(New->Blend_Map);
  773.        New->Blend_Map = Parse_Colour_Map ();
  774.      END_CASE
  775.  
  776.      CASE (PIGMENT_MAP_TOKEN)
  777.        if (TPat_Type != PIGMENT_TYPE)
  778.        {
  779.          Only_In("pigment_map","pigment");
  780.        }
  781.        if (New->Type == CHECKER_PATTERN ||
  782.            New->Type == BRICK_PATTERN ||
  783.            New->Type == HEXAGON_PATTERN ||
  784.            New->Type == PLAIN_PATTERN ||
  785.            New->Type == BITMAP_PATTERN)
  786.          Not_With ("pigment_map","this pigment type");
  787.        Destroy_Blend_Map(New->Blend_Map);
  788.        New->Blend_Map = Parse_Blend_Map (PIGMENT_TYPE,New->Type);
  789.      END_CASE
  790.  
  791.      CASE (SLOPE_MAP_TOKEN)
  792.        if (TPat_Type != NORMAL_TYPE)
  793.        {
  794.          Only_In("slope_map","normal");
  795.        }
  796.        if (New->Type == CHECKER_PATTERN ||
  797.            New->Type == BRICK_PATTERN ||
  798.            New->Type == HEXAGON_PATTERN ||
  799.            New->Type == PLAIN_PATTERN ||
  800.            New->Type == AVERAGE_PATTERN ||
  801.            New->Type == BITMAP_PATTERN)
  802.          Not_With ("slope_map","this normal type");
  803.        Destroy_Blend_Map(New->Blend_Map);
  804.        New->Blend_Map = Parse_Blend_Map (SLOPE_TYPE,New->Type);
  805.      END_CASE
  806.  
  807.      CASE (NORMAL_MAP_TOKEN)
  808.        if (TPat_Type != NORMAL_TYPE)
  809.        {
  810.          Only_In("normal_map","normal");
  811.        }
  812.        if (New->Type == CHECKER_PATTERN ||
  813.            New->Type == BRICK_PATTERN ||
  814.            New->Type == HEXAGON_PATTERN ||
  815.            New->Type == PLAIN_PATTERN ||
  816.            New->Type == BITMAP_PATTERN)
  817.          Not_With ("normal_map","this normal type");
  818.        Destroy_Blend_Map(New->Blend_Map);
  819.        New->Blend_Map = Parse_Blend_Map (NORMAL_TYPE,New->Type);
  820.      END_CASE
  821.  
  822.      CASE (TEXTURE_MAP_TOKEN)
  823.        if (TPat_Type != TEXTURE_TYPE)
  824.        {
  825.          Only_In("texture_map","texture");
  826.        }
  827.        if (New->Type == CHECKER_PATTERN ||
  828.            New->Type == BRICK_PATTERN ||
  829.            New->Type == HEXAGON_PATTERN ||
  830.            New->Type == PLAIN_PATTERN ||
  831.            New->Type == BITMAP_PATTERN)
  832.          Not_With ("texture_map","this pattern type");
  833.        Destroy_Blend_Map(New->Blend_Map);
  834.        New->Blend_Map = Parse_Blend_Map (TEXTURE_TYPE,New->Type);
  835.      END_CASE
  836.  
  837.      CASE (QUICK_COLOUR_TOKEN)
  838.        if (TPat_Type != PIGMENT_TYPE)
  839.        {
  840.          Only_In("quick_color","pigment");
  841.        }
  842.        Parse_Colour (Local_Colour);
  843.        if (opts.Quality_Flags & Q_QUICKC)
  844.        {
  845.           New->Type = PLAIN_PATTERN;
  846.           Assign_Colour(((PIGMENT *)New)->Colour,Local_Colour);
  847.        }
  848.      END_CASE
  849.  
  850.      CASE (CONTROL0_TOKEN)
  851.        if (New->Type == QUILTED_PATTERN) 
  852.        {
  853.          New->Vals.Quilted.Control0 = Parse_Float ();
  854.        }
  855.        else
  856.        {
  857.          Not_With ("control0","this normal");
  858.        }
  859.      END_CASE
  860.  
  861.      CASE (CONTROL1_TOKEN)
  862.        if (New->Type == QUILTED_PATTERN)
  863.        {
  864.          New->Vals.Quilted.Control1 = Parse_Float ();
  865.        }
  866.        else
  867.        {
  868.          Not_With ("control1","this normal");
  869.        }
  870.      END_CASE
  871.  
  872.      CASE (OCTAVES_TOKEN)
  873.        Local_Turb=Check_Turb(&(New->Warps));
  874.        Local_Turb->Octaves = (int)Parse_Float();
  875.        if(Local_Turb->Octaves < 1)
  876.           Local_Turb->Octaves = 1;
  877.        if(Local_Turb->Octaves > 10)  /* Avoid DOMAIN errors */
  878.           Local_Turb->Octaves = 10;
  879.      END_CASE
  880.  
  881.      CASE (OMEGA_TOKEN)
  882.        Local_Turb=Check_Turb(&(New->Warps));
  883.        Local_Turb->Omega = Parse_Float();
  884.      END_CASE
  885.  
  886.      CASE (LAMBDA_TOKEN)
  887.        Local_Turb=Check_Turb(&(New->Warps));
  888.        Local_Turb->Lambda = Parse_Float();
  889.      END_CASE
  890.  
  891.      CASE (FREQUENCY_TOKEN)
  892.        New->Frequency = Parse_Float();
  893.      END_CASE
  894.  
  895.      CASE (RAMP_WAVE_TOKEN)
  896.        New->Wave_Type = RAMP_WAVE;
  897.      END_CASE
  898.  
  899.      CASE (TRIANGLE_WAVE_TOKEN)
  900.        New->Wave_Type = TRIANGLE_WAVE;
  901.      END_CASE
  902.  
  903.      CASE (SINE_WAVE_TOKEN)
  904.        New->Wave_Type = SINE_WAVE;
  905.      END_CASE
  906.  
  907.      CASE (SCALLOP_WAVE_TOKEN)
  908.        New->Wave_Type = SCALLOP_WAVE;
  909.      END_CASE
  910.  
  911.      CASE (PHASE_TOKEN)
  912.        New->Phase = Parse_Float();
  913.      END_CASE
  914.  
  915.      CASE (BUMP_SIZE_TOKEN)
  916.        if (TPat_Type != NORMAL_TYPE)
  917.           Only_In ("bump_size","normal");
  918.        ((TNORMAL *)New)->Amount = Parse_Float ();
  919.      END_CASE
  920.  
  921.      CASE (AGATE_TURB_TOKEN)
  922.        if (New->Type != AGATE_PATTERN)
  923.           Not_With ("agate_turb","non-agate");
  924.        New->Vals.Agate_Turb_Scale = Parse_Float();
  925.        Check_Turb(&(New->Warps));   /* agate needs Octaves, Lambda etc. */
  926.      END_CASE
  927.  
  928.      CASE (BRICK_SIZE_TOKEN)
  929.        if (New->Type != BRICK_PATTERN)
  930.           Not_With ("brick_size","non-brick");
  931.        Parse_Vector(New->Vals.Brick.Size);
  932.      END_CASE
  933.  
  934.      CASE (MORTAR_TOKEN)
  935.        if (New->Type != BRICK_PATTERN)
  936.           Not_With ("mortar","non-brick");
  937.        New->Vals.Brick.Mortar = Parse_Float()-Small_Tolerance*2.0;
  938.      END_CASE
  939.  
  940.      CASE (WARP_TOKEN)
  941.        Parse_Warp(&(New->Warps));
  942.      END_CASE
  943.  
  944.      CASE (TRANSLATE_TOKEN)
  945.        Parse_Vector (Local_Vector);
  946.        Translate_Tpattern (New, Local_Vector);
  947.      END_CASE
  948.  
  949.      CASE (ROTATE_TOKEN)
  950.        Parse_Vector (Local_Vector);
  951.        Rotate_Tpattern (New, Local_Vector);
  952.      END_CASE
  953.  
  954.      CASE (SCALE_TOKEN)
  955.        Parse_Scale_Vector (Local_Vector);
  956.        Scale_Tpattern (New, Local_Vector);
  957.      END_CASE
  958.  
  959.      CASE (MATRIX_TOKEN)
  960.        Parse_Matrix(Local_Matrix);
  961.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  962.        Transform_Tpattern (New, &Local_Trans);
  963.      END_CASE
  964.  
  965.      CASE (TRANSFORM_TOKEN)
  966.        GET(TRANSFORM_ID_TOKEN)
  967.        Transform_Tpattern (New, (TRANSFORM *)Token.Constant_Data);
  968.      END_CASE
  969.  
  970.      OTHERWISE
  971.        UNGET
  972.        EXIT
  973.      END_CASE
  974.    END_EXPECT
  975.  
  976.    if ((TPat_Type==TEXTURE_TYPE) && (New->Type!=PLAIN_PATTERN) &&
  977.        (New->Blend_Map==NULL))
  978.    {
  979.       Error("Patterned texture must have texture_map.");
  980.    }
  981.   }
  982.  
  983.  
  984.  
  985. /*****************************************************************************
  986. *
  987. * FUNCTION
  988. *
  989. * INPUT
  990. *
  991. * OUTPUT
  992. *
  993. * RETURNS
  994. *
  995. * AUTHOR
  996. *
  997. *   POV-Ray Team
  998. *   
  999. * DESCRIPTION
  1000. *
  1001. * CHANGES
  1002. *
  1003. ******************************************************************************/
  1004.  
  1005. void Parse_Tnormal (Tnormal_Ptr)
  1006.   TNORMAL **Tnormal_Ptr;
  1007.   {
  1008.    EXPECT            /* Look for [tnormal_id] */
  1009.      CASE (TNORMAL_ID_TOKEN)
  1010.        Destroy_Tnormal(*Tnormal_Ptr);
  1011.        *Tnormal_Ptr = Copy_Tnormal ((TNORMAL *) Token.Constant_Data);
  1012.        EXIT
  1013.      END_CASE
  1014.  
  1015.      OTHERWISE
  1016.        UNGET
  1017.        EXIT
  1018.      END_CASE
  1019.    END_EXPECT    /* End [tnormal_id] */
  1020.  
  1021.    if (*Tnormal_Ptr == NULL)
  1022.      if ((Default_Texture->Tnormal) != NULL)
  1023.        *Tnormal_Ptr = Copy_Tnormal ((Default_Texture->Tnormal));
  1024.      else
  1025.        *Tnormal_Ptr = Create_Tnormal ();
  1026.  
  1027.    Parse_Pattern((TPATTERN *)*Tnormal_Ptr,NORMAL_TYPE);
  1028.   }
  1029.  
  1030.  
  1031.  
  1032. /*****************************************************************************
  1033. *
  1034. * FUNCTION
  1035. *
  1036. * INPUT
  1037. *
  1038. * OUTPUT
  1039. *
  1040. * RETURNS
  1041. *
  1042. * AUTHOR
  1043. *
  1044. *   POV-Ray Team
  1045. *   
  1046. * DESCRIPTION
  1047. *
  1048. * CHANGES
  1049. *
  1050. ******************************************************************************/
  1051.  
  1052. void Parse_Finish (Finish_Ptr)
  1053.   FINISH **Finish_Ptr;
  1054.   {
  1055.    COLOUR Temp_Colour;
  1056.    FINISH *New;
  1057.    VECTOR Local_Vector;
  1058.  
  1059.    Parse_Begin ();
  1060.  
  1061.    EXPECT        /* Look for zero or one finish_id */
  1062.      CASE (FINISH_ID_TOKEN)
  1063.        Destroy_Finish(*Finish_Ptr);
  1064.        *Finish_Ptr = Copy_Finish ((FINISH *) Token.Constant_Data);
  1065.        EXIT
  1066.      END_CASE
  1067.  
  1068.      OTHERWISE
  1069.        UNGET
  1070.        EXIT
  1071.      END_CASE
  1072.    END_EXPECT    /* End finish_id */
  1073.  
  1074.    New = *Finish_Ptr;
  1075.  
  1076.    EXPECT        /* Look for zero or more finish_body */
  1077.      CASE (AMBIENT_TOKEN)
  1078.        Parse_Colour(Temp_Colour);
  1079.        New->Ambient[RED]   = Temp_Colour[RED];
  1080.        New->Ambient[GREEN] = Temp_Colour[GREEN];
  1081.        New->Ambient[BLUE]  = Temp_Colour[BLUE];
  1082.      END_CASE
  1083.  
  1084.      CASE (BRILLIANCE_TOKEN)
  1085.        New->Brilliance = Parse_Float ();
  1086.      END_CASE
  1087.  
  1088.      CASE (DIFFUSE_TOKEN)
  1089.        New->Diffuse = Parse_Float ();
  1090.      END_CASE
  1091.  
  1092.      CASE (REFLECTION_TOKEN)
  1093.        Parse_Colour(Temp_Colour);
  1094.        New->Reflection[RED]   = Temp_Colour[RED];
  1095.        New->Reflection[GREEN] = Temp_Colour[GREEN];
  1096.        New->Reflection[BLUE]  = Temp_Colour[BLUE];
  1097.      END_CASE
  1098.  
  1099.      CASE (REFRACTION_TOKEN)
  1100.        New->Refraction = Parse_Float ();
  1101.      END_CASE
  1102.  
  1103.      CASE (IOR_TOKEN)
  1104.        New->Index_Of_Refraction = Parse_Float ();
  1105.      END_CASE
  1106.  
  1107.      CASE (PHONG_TOKEN)
  1108.        New->Phong = Parse_Float ();
  1109.      END_CASE
  1110.  
  1111.      CASE (PHONG_SIZE_TOKEN)
  1112.        New->Phong_Size = Parse_Float ();
  1113.      END_CASE
  1114.  
  1115.      CASE (SPECULAR_TOKEN)
  1116.        New->Specular = Parse_Float ();
  1117.      END_CASE
  1118.  
  1119.      CASE (ROUGHNESS_TOKEN)
  1120.        New->Roughness = Parse_Float ();
  1121.        if (New->Roughness != 0.0)
  1122.        New->Roughness = 1.0/New->Roughness; /* CEY 12/92 */
  1123.        else
  1124.          Warn(0.0, "Zero roughness used.");
  1125.      END_CASE
  1126.  
  1127.      CASE (METALLIC_TOKEN)
  1128.        New->Metallic = 1.0;
  1129.        EXPECT
  1130.          CASE_FLOAT
  1131.            New->Metallic = Parse_Float();
  1132.            EXIT
  1133.          END_CASE
  1134.  
  1135.          OTHERWISE
  1136.            UNGET
  1137.            EXIT
  1138.          END_CASE
  1139.        END_EXPECT
  1140.      END_CASE
  1141.  
  1142.      CASE (CAUSTICS_TOKEN)
  1143.        New->Caustics = Parse_Float() * 45.0;
  1144.      END_CASE
  1145.  
  1146.      CASE (CRAND_TOKEN)
  1147.        New->Crand = Parse_Float();
  1148.      END_CASE
  1149.  
  1150.      CASE (IRID_TOKEN)                     /* DMF */
  1151.        Parse_Begin();
  1152.        New->Irid = Parse_Float();
  1153.  
  1154.        EXPECT
  1155.          CASE (THICKNESS_TOKEN)           /* DMF */
  1156.            New->Irid_Film_Thickness = Parse_Float();
  1157.          END_CASE
  1158.  
  1159.          CASE (TURBULENCE_TOKEN)                /* DMF */
  1160.            Parse_Vector_Float(Local_Vector);
  1161.            New->Irid_Turb = Local_Vector[X];
  1162.          END_CASE
  1163.  
  1164.          OTHERWISE
  1165.            UNGET
  1166.            EXIT
  1167.          END_CASE
  1168.        END_EXPECT
  1169.        Parse_End();
  1170.      END_CASE
  1171.  
  1172.      CASE (FADE_DISTANCE_TOKEN)
  1173.        New->Fade_Distance = Parse_Float();
  1174.      END_CASE
  1175.  
  1176.      CASE (FADE_POWER_TOKEN)
  1177.        New->Fade_Power = Parse_Float();
  1178.      END_CASE
  1179.  
  1180.      OTHERWISE
  1181.        UNGET
  1182.        EXIT
  1183.      END_CASE
  1184.    END_EXPECT    /* End of finish_body */
  1185.  
  1186.    EXPECT        /* Look for finish_mods */
  1187.  
  1188. /*   CASE none implemented
  1189.      END_CASE     */
  1190.  
  1191.      OTHERWISE
  1192.        UNGET
  1193.        EXIT
  1194.      END_CASE
  1195.    END_EXPECT    /* End of finish_mods */
  1196.  
  1197.    Parse_End ();
  1198.   }
  1199.  
  1200.  
  1201.  
  1202. /*****************************************************************************
  1203. *
  1204. * FUNCTION
  1205. *
  1206. *   Parse_Halo
  1207. *
  1208. * INPUT
  1209. *
  1210. * OUTPUT
  1211. *
  1212. * RETURNS
  1213. *
  1214. * AUTHOR
  1215. *
  1216. *   Zsolt Szalavari
  1217. *
  1218. * DESCRIPTION
  1219. *
  1220. * CHANGES
  1221. *
  1222. *   Aug 1995 : Added and modified. [DB]
  1223. *
  1224. ******************************************************************************/
  1225.  
  1226. void Parse_Halo (Halo_Ptr)
  1227. HALO **Halo_Ptr;
  1228. {
  1229.   int add_new_halo, new_color_map, i;
  1230.   SNGL *w;
  1231.   VECTOR Local_Vector;
  1232.   MATRIX Local_Matrix;
  1233.   TRANSFORM Local_Trans;
  1234.   HALO *New, *Next_Halo;
  1235.  
  1236.   Experimental_Flag |= EF_HALOS;
  1237.  
  1238.   add_new_halo = TRUE;
  1239.  
  1240.   new_color_map = FALSE;
  1241.  
  1242.   Next_Halo = *Halo_Ptr;
  1243.  
  1244.   Parse_Begin();
  1245.  
  1246.   /* Look for [halo_id] */
  1247.  
  1248.   EXPECT
  1249.     CASE (HALO_ID_TOKEN)
  1250.       add_new_halo = FALSE;
  1251.       EXIT
  1252.     END_CASE
  1253.  
  1254.     OTHERWISE
  1255.       UNGET
  1256.       EXIT
  1257.     END_CASE
  1258.   END_EXPECT
  1259.  
  1260.   if (add_new_halo)
  1261.   {
  1262.     if ((Default_Texture->Halo) != NULL)
  1263.     {
  1264.       New = Copy_Halo((Default_Texture->Halo));
  1265.     }
  1266.     else
  1267.     {
  1268.       New = Create_Halo();
  1269.     }
  1270.   }
  1271.   else
  1272.   {
  1273.     New = Copy_Halo((HALO *)Token.Constant_Data);
  1274.   }
  1275.  
  1276.   EXPECT
  1277.     /* Look for halo rendering type. */
  1278.  
  1279.     CASE (ATTENUATING_TOKEN)
  1280.       New->Rendering_Type = HALO_ATTENUATING;
  1281.     END_CASE
  1282.  
  1283.     CASE (EMITTING_TOKEN)
  1284.       New->Rendering_Type = HALO_EMITTING;
  1285.     END_CASE
  1286.  
  1287.     CASE (GLOWING_TOKEN)
  1288.       New->Rendering_Type = HALO_GLOWING;
  1289.     END_CASE
  1290.  
  1291.     CASE (DUST_TOKEN)
  1292.       New->Rendering_Type = HALO_DUST;
  1293.     END_CASE
  1294.  
  1295.     CASE (VOLUME_RENDERED_TOKEN)
  1296.       New->Rendering_Type = HALO_VOLUME_RENDERED;
  1297.     END_CASE
  1298.  
  1299.     CASE (VOL_WITH_LIGHT_TOKEN)
  1300.       New->Rendering_Type = HALO_VOL_REND_WITH_LIGHT;
  1301.     END_CASE
  1302.  
  1303.     /* Look for halo density function. */
  1304.  
  1305.     CASE (CONSTANT_TOKEN)
  1306.       New->Type = HALO_CONSTANT;
  1307.     END_CASE
  1308.  
  1309.     CASE (LINEAR_TOKEN)
  1310.       New->Type = HALO_LINEAR;
  1311.     END_CASE
  1312.  
  1313.     CASE (CUBIC_TOKEN)
  1314.       New->Type = HALO_CUBIC;
  1315.     END_CASE
  1316.  
  1317.     CASE (POLY_TOKEN)
  1318.       New->Type = HALO_POLY;
  1319.     END_CASE
  1320.  
  1321.     CASE (VOLUME_OBJECT_TOKEN)
  1322.       New->Type = HALO_VOLUME_OBJECT;
  1323.     END_CASE
  1324.  
  1325.     /* Look for halo mapping type. */
  1326.  
  1327.     CASE (PLANAR_MAPPING_TOKEN)
  1328.       New->Mapping_Type = HALO_PLANAR_MAP;
  1329.     END_CASE
  1330.  
  1331.     CASE (SPHERICAL_MAPPING_TOKEN)
  1332.       New->Mapping_Type = HALO_SPHERICAL_MAP;
  1333.     END_CASE
  1334.  
  1335.     CASE (CYLINDRICAL_MAPPING_TOKEN)
  1336.       New->Mapping_Type = HALO_CYLINDRICAL_MAP;
  1337.     END_CASE
  1338.  
  1339.     CASE (BOX_MAPPING_TOKEN)
  1340.       New->Mapping_Type = HALO_BOX_MAP;
  1341.     END_CASE
  1342.  
  1343.     /* Look for halo sampling stuff. */
  1344.  
  1345.     CASE (SAMPLES_TOKEN)
  1346.       New->Samples = Parse_Float();
  1347.     END_CASE
  1348.  
  1349.     CASE (AA_LEVEL_TOKEN)
  1350.       if ((New->AA_Level = (int)Parse_Float()) < 0)
  1351.       {
  1352.         Error("Illegal anti-aliasing level value in halo.\n");
  1353.       }
  1354.     END_CASE
  1355.  
  1356.     CASE (AA_THRESHOLD_TOKEN)
  1357.       New->AA_Threshold = Parse_Float();
  1358.     END_CASE
  1359.  
  1360.     CASE (JITTER_TOKEN)
  1361.       New->Jitter = Parse_Float();
  1362.     END_CASE
  1363.  
  1364.     /* Look for other identifiers. */
  1365.  
  1366.     CASE (DUST_TYPE_TOKEN)
  1367.       New->Dust_Type = (char)Parse_Float();
  1368.       if ((New->Dust_Type < 1) || (New->Dust_Type > SCATTERING_TYPES))
  1369.       {
  1370.         Warn(0.0, "Unknown halo dust type.");
  1371.       }
  1372.     END_CASE
  1373.  
  1374.     CASE (MAX_VALUE_TOKEN)
  1375.       New->Max_Value = Parse_Float();
  1376.     END_CASE
  1377.  
  1378.     CASE (EXPONENT_TOKEN)
  1379.       New->Exponent = Parse_Float();
  1380.     END_CASE
  1381.  
  1382.     CASE (ECCENTRICITY_TOKEN)
  1383.       New->Eccentricity = Parse_Float();
  1384.     END_CASE
  1385.  
  1386.     CASE (COLOUR_MAP_TOKEN)
  1387.       Destroy_Blend_Map(New->Blend_Map);
  1388.       New->Blend_Map = Parse_Colour_Map();
  1389.       new_color_map = TRUE;
  1390.     END_CASE
  1391.  
  1392.     CASE (TRANSLATE_TOKEN)
  1393.       Parse_Vector (Local_Vector);
  1394.       Compute_Translation_Transform(&Local_Trans, Local_Vector);
  1395.       Translate_One_Halo (New, &Local_Trans);
  1396.      END_CASE
  1397.  
  1398.     CASE (ROTATE_TOKEN)
  1399.       Parse_Vector (Local_Vector);
  1400.       Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  1401.       Rotate_One_Halo (New, &Local_Trans);
  1402.      END_CASE
  1403.  
  1404.     CASE (SCALE_TOKEN)
  1405.       Parse_Scale_Vector (Local_Vector);
  1406.       Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  1407.       Scale_One_Halo (New, &Local_Trans);
  1408.     END_CASE
  1409.  
  1410.      CASE (MATRIX_TOKEN)
  1411.        Parse_Matrix(Local_Matrix);
  1412.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  1413.        Transform_One_Halo (New, &Local_Trans);
  1414.      END_CASE
  1415.  
  1416.     CASE (TRANSFORM_TOKEN)
  1417.       GET(TRANSFORM_ID_TOKEN)
  1418.       Transform_One_Halo (New, (TRANSFORM *)Token.Constant_Data);
  1419.     END_CASE
  1420.  
  1421.     CASE (TURBULENCE_TOKEN)
  1422.       if (New->Turb == NULL)
  1423.       {
  1424.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1425.       }
  1426.       Parse_Vector_Float(New->Turb->Turbulence);
  1427.     END_CASE
  1428.  
  1429.     CASE (OCTAVES_TOKEN)
  1430.       if (New->Turb == NULL)
  1431.       {
  1432.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1433.       }
  1434.       New->Turb->Octaves = (int)Parse_Float();
  1435.       if(New->Turb->Octaves < 1)
  1436.         New->Turb->Octaves = 1;
  1437.       if(New->Turb->Octaves > 10)
  1438.          New->Turb->Octaves = 10;
  1439.     END_CASE
  1440.  
  1441.     CASE (OMEGA_TOKEN)
  1442.       if (New->Turb == NULL)
  1443.       {
  1444.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1445.       }
  1446.       New->Turb->Omega = Parse_Float();
  1447.     END_CASE
  1448.  
  1449.     CASE (LAMBDA_TOKEN)
  1450.       if (New->Turb == NULL)
  1451.       {
  1452.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1453.       }
  1454.       New->Turb->Lambda = Parse_Float();
  1455.     END_CASE
  1456.  
  1457.     CASE (FREQUENCY_TOKEN)
  1458.       New->Frequency = Parse_Float();
  1459.     END_CASE
  1460.  
  1461.     CASE (PHASE_TOKEN)
  1462.       New->Phase = Parse_Float();
  1463.     END_CASE
  1464.  
  1465.     OTHERWISE
  1466.       UNGET
  1467.       EXIT
  1468.     END_CASE
  1469.   END_EXPECT
  1470.  
  1471.   if (Not_In_Default && (New->Type == HALO_NO_HALO))
  1472.   {
  1473.     Warn(3.0, "Halo type unspecified.");
  1474.   }
  1475.  
  1476.   Parse_End();
  1477.  
  1478.   if (New->Blend_Map == NULL)
  1479.   {
  1480.     Error("No color map specified with halo.\n");
  1481.   }
  1482.   else
  1483.   {
  1484.     if (new_color_map)
  1485.     {
  1486.       /* Convert differential translucencies to differential opacities. */
  1487.  
  1488.       for (i = 0; i < New->Blend_Map->Number_Of_Entries; i++)
  1489.       {
  1490.         w = &(New->Blend_Map->Blend_Map_Entries[i].Vals.Colour[TRANSM]);
  1491.  
  1492.         *w = 1.0 - *w;
  1493.       }
  1494.     }
  1495.   }
  1496.  
  1497.   /* Link halo to exisiting halos. */
  1498.  
  1499. /*
  1500.   if (add_new_halo)
  1501. */
  1502.   {
  1503.     New->Next_Halo = Next_Halo;
  1504.   }
  1505.  
  1506.   *Halo_Ptr = New;
  1507. }
  1508.  
  1509.  
  1510.  
  1511. /*****************************************************************************
  1512. *
  1513. * FUNCTION
  1514. *
  1515. * INPUT
  1516. *
  1517. * OUTPUT
  1518. *
  1519. * RETURNS
  1520. *
  1521. * AUTHOR
  1522. *
  1523. *   POV-Ray Team
  1524. *
  1525. * DESCRIPTION
  1526. *
  1527. * CHANGES
  1528. *
  1529. ******************************************************************************/
  1530.  
  1531. TEXTURE *Parse_Texture ()
  1532.   {
  1533.    VECTOR Local_Vector;
  1534.    MATRIX Local_Matrix;
  1535.    TRANSFORM Local_Trans;
  1536.    TEXTURE *Texture;
  1537.    int Modified_Pnf;
  1538.  
  1539.    if (opts.Language_Version < 3.0)
  1540.    {
  1541.      return(Parse_Vers1_Texture());
  1542.    }
  1543.  
  1544.    Modified_Pnf = FALSE;
  1545.  
  1546.    EXPECT               /* First allow a texture identifier */
  1547.      CASE (TEXTURE_ID_TOKEN)
  1548.        Texture = Copy_Textures((TEXTURE *) Token.Constant_Data);
  1549.        Modified_Pnf = TRUE;
  1550.        EXIT
  1551.      END_CASE
  1552.  
  1553.      OTHERWISE
  1554.        UNGET
  1555.        Texture = Copy_Textures (Default_Texture);
  1556.        EXIT
  1557.      END_CASE
  1558.    END_EXPECT
  1559.  
  1560.    /* If the texture identifer or the default texture was a PLAIN_PATTERN
  1561.       then allow its pigment, normal or finish to be overridden by
  1562.       pigment identifier, normal identifier and finish identifiers.
  1563.       This is a consession to backwards compatibility so that
  1564.       "texture{PIGMENT_IDENTIFIER}" etc. is legal even though it should
  1565.       be "texture{pigment{PIGMENT_IDENTIFIER}}"
  1566.    */
  1567.  
  1568.    /* Look for [pnf_texture] */
  1569.    if (Texture->Type == PLAIN_PATTERN)
  1570.    {
  1571.      EXPECT   /* Look for [pnf_ids] */
  1572.        CASE (PIGMENT_ID_TOKEN)
  1573.          Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  1574.          Destroy_Pigment(Texture->Pigment);
  1575.          Texture->Pigment = Copy_Pigment ((PIGMENT *) Token.Constant_Data);
  1576.          Modified_Pnf = TRUE;
  1577.        END_CASE
  1578.  
  1579.        CASE (TNORMAL_ID_TOKEN)
  1580.          Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  1581.          Destroy_Tnormal(Texture->Tnormal);
  1582.          Texture->Tnormal = Copy_Tnormal ((TNORMAL *) Token.Constant_Data);
  1583.          Modified_Pnf = TRUE;
  1584.        END_CASE
  1585.  
  1586.        CASE (FINISH_ID_TOKEN)
  1587.          Warn_State(Token.Token_Id, FINISH_TOKEN);
  1588.          Destroy_Finish(Texture->Finish);
  1589.          Texture->Finish = Copy_Finish ((FINISH *) Token.Constant_Data);
  1590.          Modified_Pnf = TRUE;
  1591.        END_CASE
  1592.  
  1593.        CASE (HALO_ID_TOKEN)
  1594.          Warn_State(Token.Token_Id, HALO_TOKEN);
  1595.          Destroy_Halo(Texture->Halo);
  1596.          Texture->Halo = Copy_Halo ((HALO *) Token.Constant_Data);
  1597.          Modified_Pnf = TRUE;
  1598.        END_CASE
  1599.  
  1600.        OTHERWISE
  1601.          UNGET
  1602.          EXIT
  1603.        END_CASE
  1604.      END_EXPECT
  1605.  
  1606.    /* If the texture identifer or the default texture was a PLAIN_PATTERN
  1607.       then allow its pigment, normal or finish to be overridden by
  1608.       pigment, normal or finish statement.  Also allow transformations.
  1609.    */
  1610.  
  1611.      EXPECT   /* Modify previous pnf */
  1612.        CASE (PIGMENT_TOKEN)
  1613.          Parse_Begin ();
  1614.          Parse_Pigment ( &(Texture->Pigment) );
  1615.          Parse_End ();
  1616.          Modified_Pnf = TRUE;
  1617.        END_CASE
  1618.  
  1619.        CASE (TNORMAL_TOKEN)
  1620.          Parse_Begin ();
  1621.          Parse_Tnormal ( &(Texture->Tnormal) );
  1622.          Parse_End ();
  1623.          Modified_Pnf = TRUE;
  1624.        END_CASE
  1625.  
  1626.        CASE (FINISH_TOKEN)
  1627.          Parse_Finish ( &(Texture->Finish) );
  1628.          Modified_Pnf = TRUE;
  1629.        END_CASE
  1630.  
  1631.        CASE (HALO_TOKEN)
  1632.          Parse_Halo(&(Texture->Halo));
  1633.          Modified_Pnf = TRUE;
  1634.        END_CASE
  1635.  
  1636.        CASE (TRANSLATE_TOKEN)
  1637.          Parse_Vector (Local_Vector);
  1638.          Compute_Translation_Transform(&Local_Trans, Local_Vector);
  1639.          Translate_Textures (Texture, &Local_Trans);
  1640.          Modified_Pnf = TRUE;
  1641.        END_CASE
  1642.  
  1643.        CASE (ROTATE_TOKEN)
  1644.          Parse_Vector (Local_Vector);
  1645.          Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  1646.          Rotate_Textures (Texture, &Local_Trans);
  1647.          Modified_Pnf = TRUE;
  1648.        END_CASE
  1649.  
  1650.        CASE (SCALE_TOKEN)
  1651.          Parse_Scale_Vector (Local_Vector);
  1652.          Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  1653.          Scale_Textures (Texture, &Local_Trans);
  1654.          Modified_Pnf = TRUE;
  1655.        END_CASE
  1656.  
  1657.        CASE (MATRIX_TOKEN)
  1658.          Parse_Matrix(Local_Matrix);
  1659.          Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  1660.          Transform_Textures (Texture, &Local_Trans);
  1661.          Modified_Pnf = TRUE;
  1662.        END_CASE
  1663.  
  1664.        CASE (TRANSFORM_TOKEN)
  1665.          GET(TRANSFORM_ID_TOKEN)
  1666.          Transform_Textures (Texture, (TRANSFORM *)Token.Constant_Data);
  1667.          Modified_Pnf = TRUE;
  1668.        END_CASE
  1669.  
  1670.        OTHERWISE
  1671.          UNGET
  1672.          EXIT
  1673.        END_CASE
  1674.      END_EXPECT
  1675.     }
  1676.     else
  1677.     {
  1678.     /* Here it is not a PLAIN_PATTERN texture and since default textures
  1679.        must be plain then this was a texture identifier that was a special 
  1680.        texture.  Allow transforms.  The "if(!Modified_Pnf)..." below
  1681.        will always fail if we came here.  So we return after the
  1682.        transforms. */
  1683.       Parse_Texture_Transform(Texture);
  1684.     }
  1685.  
  1686.     /* If we've modified the default texture with a p,n, or f then this
  1687.        has to stay a PLAIN_PATTERN pnf texture.  We won't allow
  1688.        a texture_map or pattern.  Therefore quit now.
  1689.      */
  1690.  
  1691.     if (!Modified_Pnf)
  1692.     {
  1693.      /* At this point we've either got a texture statement that had
  1694.         no p, n or f.  Nor any texture identifier.  Its probably 
  1695.         a patterned texture_map texture. */
  1696.        
  1697.        EXPECT
  1698.          CASE (TILES_TOKEN)
  1699.            Destroy_Textures (Texture);
  1700.            Texture = Parse_Tiles();
  1701.            Parse_Texture_Transform(Texture);
  1702.            EXIT
  1703.          END_CASE
  1704.  
  1705.          CASE (MATERIAL_MAP_TOKEN)
  1706.            Destroy_Textures (Texture);
  1707.            Texture = Parse_Material_Map ();
  1708.            Parse_Texture_Transform(Texture);
  1709.            EXIT
  1710.          END_CASE
  1711.  
  1712.          OTHERWISE
  1713.            UNGET;
  1714.            Parse_Pattern((TPATTERN *)Texture,TEXTURE_TYPE);
  1715.            /* If it was a patterned texture_map the destroy its
  1716.               p, n, f & h.  If not, it must be a totally empty
  1717.               default texture.  Allow it to be transformed. */
  1718.            if (Texture->Type != PLAIN_PATTERN)
  1719.            {
  1720.              Destroy_Pigment(Texture->Pigment);
  1721.              Destroy_Tnormal(Texture->Tnormal);
  1722.              Destroy_Finish(Texture->Finish);
  1723.              Destroy_Halo(Texture->Halo);
  1724.              Texture->Pigment = NULL;
  1725.              Texture->Tnormal = NULL;
  1726.              Texture->Finish  = NULL;
  1727.              Texture->Halo    = NULL;
  1728.            }
  1729.            else
  1730.            {
  1731.              Parse_Texture_Transform(Texture);
  1732.            }
  1733.            EXIT
  1734.          END_CASE
  1735.       END_EXPECT
  1736.     }
  1737.  
  1738.     return (Texture);
  1739.   }
  1740.  
  1741.  
  1742.  
  1743. /*****************************************************************************
  1744. *
  1745. * FUNCTION
  1746. *
  1747. * INPUT
  1748. *
  1749. * OUTPUT
  1750. *
  1751. * RETURNS
  1752. *
  1753. * AUTHOR
  1754. *
  1755. *   POV-Ray Team
  1756. *   
  1757. * DESCRIPTION
  1758. *
  1759. * CHANGES
  1760. *
  1761. ******************************************************************************/
  1762.  
  1763. static TEXTURE *Parse_Tiles()
  1764. {
  1765.   TEXTURE *Texture, *Local_Texture;
  1766.   BLEND_MAP_ENTRY *Entry;
  1767.  
  1768.   Parse_Begin ();
  1769.  
  1770.   Texture = Create_Texture ();
  1771.   Destroy_Pigment(Texture->Pigment);
  1772.   Destroy_Tnormal(Texture->Tnormal);
  1773.   Destroy_Finish(Texture->Finish);
  1774.   Destroy_Halo(Texture->Halo);
  1775.   Texture->Pigment = NULL;
  1776.   Texture->Tnormal = NULL;
  1777.   Texture->Finish  = NULL;
  1778.   Texture->Halo    = NULL;
  1779.   Texture->Type = CHECKER_PATTERN;
  1780.  
  1781.   Texture->Blend_Map = Create_Blend_Map();
  1782.   Texture->Blend_Map->Number_Of_Entries = 2;
  1783.   Texture->Blend_Map->Blend_Map_Entries = Entry = Create_BMap_Entries (2);
  1784.   Texture->Blend_Map->Type = TEXTURE_TYPE;
  1785.   Entry[0].Vals.Texture=NULL;
  1786.   Entry[0].value=0.0;
  1787.   Entry[0].Same=FALSE;
  1788.   Entry[1].Vals.Texture=NULL;
  1789.   Entry[1].value=1.0;
  1790.   Entry[1].Same=FALSE;
  1791.   
  1792.   /* Note first tile is 1, 2nd tile is 0 to keep compatible with old tiles */
  1793.  
  1794.   EXPECT
  1795.     CASE (TEXTURE_TOKEN)
  1796.       Parse_Begin ();
  1797.       Local_Texture = Parse_Texture ();
  1798.       Link_Textures(&(Entry[1].Vals.Texture),Local_Texture);
  1799.       Parse_End ();
  1800.     END_CASE
  1801.  
  1802.     OTHERWISE
  1803.       UNGET
  1804.       EXIT
  1805.     END_CASE
  1806.   END_EXPECT
  1807.  
  1808.   GET (TILE2_TOKEN);
  1809.  
  1810.   EXPECT
  1811.     CASE (TEXTURE_TOKEN)
  1812.       Parse_Begin ();
  1813.       Local_Texture = Parse_Texture ();
  1814.       Link_Textures(&(Entry[0].Vals.Texture),Local_Texture);
  1815.       Parse_End ();
  1816.     END_CASE
  1817.  
  1818.     OTHERWISE
  1819.       UNGET
  1820.       EXIT
  1821.     END_CASE
  1822.   END_EXPECT
  1823.  
  1824.   Parse_End ();
  1825.  
  1826.   return (Texture);
  1827. }
  1828.  
  1829.  
  1830.  
  1831. /*****************************************************************************
  1832. *
  1833. * FUNCTION
  1834. *
  1835. * INPUT
  1836. *
  1837. * OUTPUT
  1838. *
  1839. * RETURNS
  1840. *
  1841. * AUTHOR
  1842. *
  1843. *   POV-Ray Team
  1844. *   
  1845. * DESCRIPTION
  1846. *
  1847. * CHANGES
  1848. *
  1849. ******************************************************************************/
  1850.  
  1851. static TEXTURE *Parse_Material_Map()
  1852. {
  1853.   TEXTURE *Texture, *Local_Texture;
  1854.   Parse_Begin ();
  1855.  
  1856.   Texture = Create_Texture ();
  1857.   Destroy_Pigment(Texture->Pigment);
  1858.   Destroy_Tnormal(Texture->Tnormal);
  1859.   Destroy_Finish(Texture->Finish);
  1860.   Destroy_Halo(Texture->Halo);
  1861.   Texture->Pigment = NULL;
  1862.   Texture->Tnormal = NULL;
  1863.   Texture->Finish  = NULL;
  1864.   Texture->Halo    = NULL;
  1865.   Texture->Type = BITMAP_PATTERN;
  1866.  
  1867.   Texture->Vals.Image = Parse_Image(MATERIAL_FILE);
  1868.   Texture->Vals.Image->Use_Colour_Flag = FALSE;
  1869.  
  1870.   EXPECT
  1871.     CASE (ONCE_TOKEN)
  1872.       Texture->Vals.Image->Once_Flag=TRUE;
  1873.     END_CASE
  1874.  
  1875.     CASE (INTERPOLATE_TOKEN)
  1876.       Texture->Vals.Image->Interpolation_Type=(int)Parse_Float();
  1877.     END_CASE
  1878.  
  1879.     CASE (MAP_TYPE_TOKEN)
  1880.       Texture->Vals.Image->Map_Type = (int) Parse_Float ();
  1881.     END_CASE
  1882.  
  1883.     OTHERWISE
  1884.       UNGET
  1885.       EXIT
  1886.     END_CASE
  1887.   END_EXPECT
  1888.  
  1889.   GET (TEXTURE_TOKEN)                /* First material */
  1890.   Parse_Begin();
  1891.   Texture->Materials = Local_Texture = Parse_Texture ();
  1892.   Parse_End();
  1893.   Texture->Num_Of_Mats++;
  1894.  
  1895.   EXPECT                             /* Subsequent materials */
  1896.     CASE (TEXTURE_TOKEN)
  1897.       Parse_Begin();
  1898.       Local_Texture->Next_Material = Parse_Texture ();
  1899.       Parse_End();
  1900.       Local_Texture = Local_Texture->Next_Material;
  1901.       Texture->Num_Of_Mats++;
  1902.     END_CASE
  1903.  
  1904.     OTHERWISE
  1905.       UNGET
  1906.       EXIT
  1907.     END_CASE
  1908.   END_EXPECT
  1909.  
  1910.   Parse_End ();
  1911.   
  1912.   return(Texture);
  1913. }
  1914.      
  1915.  
  1916.  
  1917. /*****************************************************************************
  1918. *
  1919. * FUNCTION
  1920. *
  1921. * INPUT
  1922. *
  1923. * OUTPUT
  1924. *
  1925. * RETURNS
  1926. *
  1927. * AUTHOR
  1928. *
  1929. *   POV-Ray Team
  1930. *   
  1931. * DESCRIPTION
  1932. *
  1933. * CHANGES
  1934. *
  1935. ******************************************************************************/
  1936.  
  1937. static TEXTURE *Parse_Vers1_Texture ()
  1938. {
  1939.    VECTOR Local_Vector;
  1940.    COLOUR Local_Colour;
  1941.    MATRIX Local_Matrix;
  1942.    TRANSFORM Local_Trans;
  1943.    TURB *Local_Turb;
  1944.    TEXTURE *Texture;
  1945.    PIGMENT *Pigment;
  1946.    TNORMAL *Tnormal;
  1947.    FINISH *Finish;
  1948.  
  1949.    EXPECT                      /* Look for texture_body */
  1950.      CASE (TILES_TOKEN)
  1951.        Texture = Parse_Tiles();
  1952.        EXIT
  1953.      END_CASE
  1954.  
  1955.      CASE (MATERIAL_MAP_TOKEN)
  1956.        Texture = Parse_Material_Map ();
  1957.        EXIT
  1958.      END_CASE
  1959.  
  1960.      CASE (TEXTURE_ID_TOKEN)
  1961.        Texture = Copy_Textures((TEXTURE *) Token.Constant_Data);
  1962.        EXIT
  1963.      END_CASE
  1964.  
  1965.      OTHERWISE
  1966.        UNGET
  1967.        Texture = Copy_Textures (Default_Texture);
  1968.        EXIT
  1969.      END_CASE
  1970.    END_EXPECT
  1971.  
  1972.    /* Look for [pnf_texture] */
  1973.    if (Texture->Type == PLAIN_PATTERN)
  1974.      {
  1975.        EXPECT   /* Look for [pnf_ids] */
  1976.          CASE (PIGMENT_ID_TOKEN)
  1977.            Destroy_Pigment(Texture->Pigment);
  1978.            Texture->Pigment = Copy_Pigment ((PIGMENT *) Token.Constant_Data);
  1979.          END_CASE
  1980.  
  1981.          CASE (TNORMAL_ID_TOKEN)
  1982.            Destroy_Tnormal(Texture->Tnormal);
  1983.            Texture->Tnormal = Copy_Tnormal ((TNORMAL *) Token.Constant_Data);
  1984.          END_CASE
  1985.  
  1986.          CASE (FINISH_ID_TOKEN)
  1987.            Destroy_Finish(Texture->Finish);
  1988.            Texture->Finish = Copy_Finish ((FINISH *) Token.Constant_Data);
  1989.          END_CASE
  1990.  
  1991.          OTHERWISE
  1992.            UNGET
  1993.            EXIT
  1994.          END_CASE
  1995.        END_EXPECT
  1996.  
  1997.        Pigment = Texture->Pigment;
  1998.        Tnormal = Texture->Tnormal;
  1999.        Finish  = Texture->Finish;
  2000.   /*     Halo    = Texture->Halo;*/
  2001.  
  2002.        EXPECT
  2003.          CASE (PIGMENT_TOKEN)
  2004.            Parse_Begin ();
  2005.            Parse_Pigment ( &(Texture->Pigment) );
  2006.            Parse_End ();
  2007.          END_CASE
  2008.  
  2009.          CASE (TNORMAL_TOKEN)
  2010.            Parse_Begin ();
  2011.            Parse_Tnormal ( &(Texture->Tnormal) );
  2012.            Parse_End ();
  2013.          END_CASE
  2014.  
  2015.          CASE (FINISH_TOKEN)
  2016.            Parse_Finish ( &(Texture->Finish) );
  2017.          END_CASE
  2018.  
  2019. /***********************************************************************
  2020. PIGMENT STUFF OUTSIDE PIGMENT{}
  2021. NOTE: Do not add new keywords to this section.  Use 1.0 syntax only.
  2022. ***********************************************************************/
  2023.          CASE (AGATE_TOKEN)
  2024.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2025.            Pigment->Type = AGATE_PATTERN;
  2026.            Pigment->Vals.Agate_Turb_Scale = 1.0;
  2027.            Check_Turb(&(Pigment->Warps));   /* agate needs Octaves, Lambda etc. */
  2028.          END_CASE
  2029.  
  2030.          CASE (BOZO_TOKEN)
  2031.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2032.            Pigment->Type = BOZO_PATTERN;
  2033.          END_CASE
  2034.  
  2035.          CASE (GRANITE_TOKEN)
  2036.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2037.            Pigment->Type = GRANITE_PATTERN;
  2038.          END_CASE
  2039.  
  2040.          CASE (LEOPARD_TOKEN)
  2041.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2042.            Pigment->Type = LEOPARD_PATTERN;
  2043.          END_CASE
  2044.  
  2045.          CASE (MARBLE_TOKEN)
  2046.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2047.            Pigment->Type = MARBLE_PATTERN;
  2048.          END_CASE
  2049.  
  2050.          CASE (MANDEL_TOKEN)
  2051.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2052.            Pigment->Type = MANDEL_PATTERN;
  2053.            Pigment->Vals.Iterations = (int)Parse_Float();
  2054.          END_CASE
  2055.  
  2056.          CASE (ONION_TOKEN)
  2057.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2058.            Pigment->Type = ONION_PATTERN;
  2059.          END_CASE
  2060.  
  2061.          CASE (PATTERN1_TOKEN)
  2062.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2063.            Pigment->Type = PATTERN1_PATTERN;
  2064.          END_CASE
  2065.  
  2066.          CASE (PATTERN2_TOKEN)
  2067.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2068.            Pigment->Type = PATTERN2_PATTERN;
  2069.          END_CASE
  2070.  
  2071.          CASE (PATTERN3_TOKEN)
  2072.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2073.            Pigment->Type = PATTERN3_PATTERN;
  2074.          END_CASE
  2075.  
  2076.          CASE (SPOTTED_TOKEN)
  2077.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2078.            Pigment->Type = SPOTTED_PATTERN;
  2079.          END_CASE
  2080.  
  2081.          CASE (WOOD_TOKEN)
  2082.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2083.            Pigment->Type = WOOD_PATTERN;
  2084.          END_CASE
  2085.  
  2086.          CASE (GRADIENT_TOKEN)
  2087.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2088.            Pigment->Type = GRADIENT_PATTERN;
  2089.            Parse_Vector (Pigment->Vals.Gradient);
  2090.          END_CASE
  2091.  
  2092.          CASE_COLOUR
  2093.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2094.            Pigment->Type = PLAIN_PATTERN;
  2095.            Parse_Colour (Pigment->Colour);
  2096.          END_CASE
  2097.  
  2098.          CASE (CHECKER_TOKEN)
  2099.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2100.            Pigment->Type = CHECKER_PATTERN;
  2101.            Pigment->Frequency = 0.0;
  2102.            Destroy_Blend_Map(Pigment->Blend_Map);
  2103.            Pigment->Blend_Map = Parse_Blend_List(2,&Check_Default_Map,COLOUR_TYPE);
  2104.          END_CASE
  2105.  
  2106.          CASE (HEXAGON_TOKEN)
  2107.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2108.            Pigment->Type = HEXAGON_PATTERN;
  2109.            Pigment->Frequency = 0.0;
  2110.            Destroy_Blend_Map(Pigment->Blend_Map);
  2111.            Pigment->Blend_Map = Parse_Blend_List(3,&Hex_Default_Map,COLOUR_TYPE);
  2112.          END_CASE
  2113.  
  2114.          CASE (IMAGE_MAP_TOKEN)
  2115.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2116.            Pigment->Type = BITMAP_PATTERN;
  2117.            Pigment->Frequency = 0.0;
  2118.            Parse_Image_Map (Pigment);
  2119.          END_CASE
  2120.  
  2121.          CASE (TURBULENCE_TOKEN)
  2122.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2123.            Parse_Vector_Float(Local_Turb->Turbulence);
  2124.          END_CASE
  2125.  
  2126.          CASE (COLOUR_MAP_TOKEN)
  2127.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2128.            if (Pigment->Type == CHECKER_PATTERN ||
  2129.                Pigment->Type == HEXAGON_PATTERN ||
  2130.                Pigment->Type == PLAIN_PATTERN ||
  2131.                Pigment->Type == BITMAP_PATTERN)
  2132.              Warn(1.5, "Cannot use color map with this pigment type.");
  2133.            Destroy_Blend_Map(Pigment->Blend_Map);
  2134.            Pigment->Blend_Map = Parse_Colour_Map ();
  2135.          END_CASE
  2136.  
  2137.          CASE (QUICK_COLOUR_TOKEN)
  2138.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2139.            Parse_Colour (Local_Colour);
  2140.            if (opts.Quality_Flags & Q_QUICKC)
  2141.            {
  2142.               Assign_Colour(Pigment->Colour,Local_Colour);
  2143.            }
  2144.          END_CASE
  2145.  
  2146.          CASE (OCTAVES_TOKEN)
  2147.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2148.            Local_Turb->Octaves = (int)Parse_Float();
  2149.            if(Local_Turb->Octaves < 1)
  2150.               Local_Turb->Octaves = 1;
  2151.            if(Local_Turb->Octaves > 10)  /* Avoid DOMAIN errors */
  2152.               Local_Turb->Octaves = 10;
  2153.          END_CASE
  2154.  
  2155.          CASE (OMEGA_TOKEN)
  2156.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2157.            Local_Turb->Omega = Parse_Float();
  2158.          END_CASE
  2159.  
  2160.          CASE (LAMBDA_TOKEN)
  2161.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2162.            Local_Turb->Lambda = Parse_Float();
  2163.          END_CASE
  2164.  
  2165. /***********************************************************************
  2166. TNORMAL STUFF OUTSIDE NORMAL{}
  2167. NOTE: Do not add new keywords to this section.  Use 1.0 syntax only.
  2168. ***********************************************************************/
  2169.          CASE (BUMPS_TOKEN)
  2170.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2171.            ADD_TNORMAL
  2172.            Tnormal->Type = BUMPS_PATTERN;
  2173.            Tnormal->Amount = Parse_Float ();
  2174.          END_CASE
  2175.  
  2176.          CASE (BUMPY1_TOKEN)
  2177.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2178.            ADD_TNORMAL
  2179.            Tnormal->Type = BUMPY1_PATTERN;
  2180.            Tnormal->Amount = Parse_Float ();
  2181.          END_CASE
  2182.  
  2183.          CASE (BUMPY2_TOKEN)
  2184.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2185.            ADD_TNORMAL
  2186.            Tnormal->Type = BUMPY2_PATTERN;
  2187.            Tnormal->Amount = Parse_Float ();
  2188.          END_CASE
  2189.  
  2190.          CASE (BUMPY3_TOKEN)
  2191.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2192.            ADD_TNORMAL
  2193.            Tnormal->Type = BUMPY3_PATTERN;
  2194.            Tnormal->Amount = Parse_Float ();
  2195.          END_CASE
  2196.  
  2197.          CASE (DENTS_TOKEN)
  2198.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2199.            ADD_TNORMAL
  2200.            Tnormal->Type = DENTS_PATTERN;
  2201.            Tnormal->Amount = Parse_Float ();
  2202.          END_CASE
  2203.  
  2204.          CASE (RIPPLES_TOKEN)
  2205.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2206.            ADD_TNORMAL
  2207.            Tnormal->Type = RIPPLES_PATTERN;
  2208.            Tnormal->Amount = Parse_Float ();
  2209.          END_CASE
  2210.  
  2211.          CASE (WAVES_TOKEN)
  2212.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2213.            ADD_TNORMAL
  2214.            Tnormal->Type = WAVES_PATTERN;
  2215.            Tnormal->Amount = Parse_Float ();
  2216.          END_CASE
  2217.  
  2218.          CASE (WRINKLES_TOKEN)
  2219.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2220.            ADD_TNORMAL
  2221.            Tnormal->Type = WRINKLES_PATTERN;
  2222.            Tnormal->Amount = Parse_Float ();
  2223.          END_CASE
  2224.  
  2225.          CASE (BUMP_MAP_TOKEN)
  2226.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2227.            ADD_TNORMAL
  2228.            Tnormal->Type = BITMAP_PATTERN;
  2229.            Tnormal->Frequency = 0.0;
  2230.            Parse_Bump_Map (Tnormal);
  2231.          END_CASE
  2232.  
  2233.          CASE (FREQUENCY_TOKEN)
  2234.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2235.            ADD_TNORMAL
  2236.            if (!(Tnormal->Type == RIPPLES_PATTERN || Tnormal->Type == WAVES_PATTERN))
  2237.              if (opts.Language_Version >= 1.5)
  2238.                Warn(1.5, "Cannot use frequency with this normal.");
  2239.            Tnormal->Frequency = Parse_Float();
  2240.          END_CASE
  2241.  
  2242.          CASE (PHASE_TOKEN)
  2243.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2244.            ADD_TNORMAL
  2245.            if (!(Tnormal->Type == RIPPLES_PATTERN || Tnormal->Type == WAVES_PATTERN))
  2246.              if (opts.Language_Version >= 1.5)
  2247.                Warn(1.5, "Cannot use phase with this normal.");
  2248.            Tnormal->Phase = Parse_Float();
  2249.          END_CASE
  2250.  
  2251.  
  2252. /***********************************************************************
  2253. FINISH STUFF OUTSIDE FINISH{}
  2254. NOTE: Do not add new keywords to this section.  Use 1.0 syntax only.
  2255. ***********************************************************************/
  2256.          CASE (AMBIENT_TOKEN)
  2257.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2258.            Finish->Ambient[RED]   =
  2259.            Finish->Ambient[GREEN] =
  2260.            Finish->Ambient[BLUE]  = Parse_Float ();
  2261.          END_CASE
  2262.  
  2263.          CASE (BRILLIANCE_TOKEN)
  2264.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2265.            Finish->Brilliance = Parse_Float ();
  2266.          END_CASE
  2267.  
  2268.          CASE (DIFFUSE_TOKEN)
  2269.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2270.            Finish->Diffuse = Parse_Float ();
  2271.          END_CASE
  2272.  
  2273.          CASE (REFLECTION_TOKEN)
  2274.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2275.            Finish->Reflection[RED]   =
  2276.            Finish->Reflection[GREEN] =
  2277.            Finish->Reflection[BLUE]  = Parse_Float ();
  2278.          END_CASE
  2279.  
  2280.          CASE (REFRACTION_TOKEN)
  2281.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2282.            Finish->Refraction = Parse_Float ();
  2283.          END_CASE
  2284.  
  2285.          CASE (IOR_TOKEN)
  2286.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2287.            Finish->Index_Of_Refraction = Parse_Float ();
  2288.          END_CASE
  2289.  
  2290.          CASE (PHONG_TOKEN)
  2291.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2292.            Finish->Phong = Parse_Float ();
  2293.          END_CASE
  2294.  
  2295.          CASE (PHONG_SIZE_TOKEN)
  2296.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2297.            Finish->Phong_Size = Parse_Float ();
  2298.          END_CASE
  2299.  
  2300.          CASE (SPECULAR_TOKEN)
  2301.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2302.            Finish->Specular = Parse_Float ();
  2303.          END_CASE
  2304.  
  2305.          CASE (ROUGHNESS_TOKEN)
  2306.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2307.            Finish->Roughness = Parse_Float ();
  2308.            if (Finish->Roughness != 0.0)
  2309.            Finish->Roughness = 1.0/Finish->Roughness; /* CEY 12/92 */
  2310.            else
  2311.              Warn(0.0, "Zero roughness used.");
  2312.          END_CASE
  2313.  
  2314.          CASE (METALLIC_TOKEN)
  2315.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2316.            Finish->Metallic = 1.0;
  2317.          END_CASE
  2318.  
  2319.          CASE (CRAND_TOKEN)
  2320.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2321.            Finish->Crand = Parse_Float();
  2322.          END_CASE
  2323.  
  2324.          CASE_FLOAT
  2325.            Finish->Crand = Parse_Float();
  2326.            Warn(1.5, "Should use crand keyword in finish statement.");
  2327.          END_CASE
  2328.  
  2329.          CASE (TRANSLATE_TOKEN)
  2330.            Parse_Vector (Local_Vector);
  2331.            Compute_Translation_Transform(&Local_Trans, Local_Vector);
  2332.            Translate_Textures (Texture, &Local_Trans);
  2333.          END_CASE
  2334.  
  2335.          CASE (ROTATE_TOKEN)
  2336.            Parse_Vector (Local_Vector);
  2337.            Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  2338.            Rotate_Textures (Texture, &Local_Trans);
  2339.          END_CASE
  2340.  
  2341.          CASE (SCALE_TOKEN)
  2342.            Parse_Scale_Vector (Local_Vector);
  2343.            Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  2344.            Scale_Textures (Texture, &Local_Trans);
  2345.          END_CASE
  2346.  
  2347.          CASE (MATRIX_TOKEN)
  2348.            Parse_Matrix(Local_Matrix);
  2349.            Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  2350.            Transform_Textures (Texture, &Local_Trans);
  2351.          END_CASE
  2352.  
  2353.          CASE (TRANSFORM_TOKEN)
  2354.            GET(TRANSFORM_ID_TOKEN)
  2355.            Transform_Textures (Texture, (TRANSFORM *)Token.Constant_Data);
  2356.          END_CASE
  2357.  
  2358.          CASE (TEXTURE_ID_TOKEN)
  2359.            Warn(0.0, "Texture identifier overwriting previous values.");
  2360.            Destroy_Textures(Texture);
  2361.            Texture = Copy_Textures((TEXTURE *) Token.Constant_Data);
  2362.            Pigment = Texture->Pigment;
  2363.            Tnormal = Texture->Tnormal;
  2364.            Finish  = Texture->Finish;
  2365.   /*         Halo    = Texture->Halo;*/
  2366.          END_CASE
  2367.  
  2368.          OTHERWISE
  2369.            UNGET
  2370.            EXIT
  2371.          END_CASE
  2372. /***********************************************************************/
  2373.  
  2374.        END_EXPECT
  2375.  
  2376.        if (Not_In_Default && (Texture->Pigment->Type == NO_PATTERN) &&
  2377.            !(opts.Language_Version < 1.5))
  2378.          Parse_Error(PIGMENT_ID_TOKEN);
  2379.  
  2380.      }
  2381.  
  2382.    Parse_Texture_Transform(Texture);
  2383.  
  2384.    return (Texture);
  2385.   }
  2386.  
  2387.  
  2388.  
  2389. /*****************************************************************************
  2390. *
  2391. * FUNCTION
  2392. *
  2393. * INPUT
  2394. *
  2395. * OUTPUT
  2396. *
  2397. * RETURNS
  2398. *
  2399. * AUTHOR
  2400. *
  2401. *   POV-Ray Team
  2402. *   
  2403. * DESCRIPTION
  2404. *
  2405. * CHANGES
  2406. *
  2407. ******************************************************************************/
  2408.  
  2409. static void Parse_Texture_Transform (Texture)
  2410. TEXTURE *Texture;
  2411. {
  2412.    VECTOR Local_Vector;
  2413.    MATRIX Local_Matrix;
  2414.    TRANSFORM Local_Trans;
  2415.  
  2416.    EXPECT
  2417.      CASE (TRANSLATE_TOKEN)
  2418.        Parse_Vector (Local_Vector);
  2419.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  2420.        Translate_Textures (Texture, &Local_Trans);
  2421.      END_CASE
  2422.  
  2423.      CASE (ROTATE_TOKEN)
  2424.        Parse_Vector (Local_Vector);
  2425.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  2426.        Rotate_Textures (Texture, &Local_Trans);
  2427.      END_CASE
  2428.  
  2429.      CASE (SCALE_TOKEN)
  2430.        Parse_Scale_Vector (Local_Vector);
  2431.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  2432.        Scale_Textures (Texture, &Local_Trans);
  2433.      END_CASE
  2434.  
  2435.      CASE (MATRIX_TOKEN)
  2436.        Parse_Matrix(Local_Matrix);
  2437.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  2438.        Transform_Textures (Texture, &Local_Trans);
  2439.      END_CASE
  2440.  
  2441.      CASE (TRANSFORM_TOKEN)
  2442.        GET(TRANSFORM_ID_TOKEN)
  2443.        Transform_Textures (Texture, (TRANSFORM *)Token.Constant_Data);
  2444.      END_CASE
  2445.  
  2446.      OTHERWISE
  2447.        UNGET
  2448.        EXIT
  2449.      END_CASE
  2450.    END_EXPECT
  2451. }
  2452.  
  2453.  
  2454. /*****************************************************************************
  2455. *
  2456. * FUNCTION
  2457. *
  2458. *   Parse_Atmosphere
  2459. *
  2460. * INPUT
  2461. *
  2462. * OUTPUT
  2463. *   
  2464. * RETURNS
  2465. *   
  2466. * AUTHOR
  2467. *
  2468. *   Dieter Bayer
  2469. *   
  2470. * DESCRIPTION
  2471. *
  2472. *   -
  2473. *
  2474. * CHANGES
  2475. *
  2476. *   Nov 1994 : Creation.
  2477. *
  2478. ******************************************************************************/
  2479.  
  2480. ATMOSPHERE *Parse_Atmosphere()
  2481. {
  2482.   ATMOSPHERE *Atmosphere;
  2483.  
  2484.   Experimental_Flag |= EF_ATMOS;
  2485.  
  2486.   Parse_Begin();
  2487.  
  2488.   EXPECT
  2489.     CASE(ATMOSPHERE_ID_TOKEN)
  2490.       Atmosphere = Copy_Atmosphere((ATMOSPHERE *)Token.Constant_Data);
  2491.       EXIT
  2492.     END_CASE
  2493.  
  2494.     OTHERWISE
  2495.       UNGET
  2496.         Atmosphere = Create_Atmosphere();
  2497.       EXIT
  2498.     END_CASE
  2499.   END_EXPECT
  2500.  
  2501.   EXPECT
  2502.     CASE (TYPE_TOKEN)
  2503.       Atmosphere->Type = (int)Parse_Float();
  2504.       if ((Atmosphere->Type < 1) || (Atmosphere->Type > SCATTERING_TYPES))
  2505.       {
  2506.         Warn(0.0, "Unknown atmospheric scattering type.");
  2507.       }
  2508.     END_CASE
  2509.  
  2510.     CASE (DISTANCE_TOKEN)
  2511.       Atmosphere->Distance = Parse_Float();
  2512.     END_CASE
  2513.  
  2514.     CASE (SAMPLES_TOKEN)
  2515.       if ((Atmosphere->Samples = (int)Parse_Float()) < 1)
  2516.       {
  2517.         Error("Illegal samples value in atmosphere.\n");
  2518.       }
  2519.     END_CASE
  2520.  
  2521.     CASE (SCATTERING_TOKEN)
  2522.       Atmosphere->Scattering = Parse_Float();
  2523.     END_CASE
  2524.  
  2525.     CASE (AA_LEVEL_TOKEN)
  2526.       if ((Atmosphere->AA_Level = (int)Parse_Float()) < 0)
  2527.       {
  2528.         Error("Illegal level value in atmosphere.\n");
  2529.       }
  2530.     END_CASE
  2531.  
  2532.     CASE (AA_THRESHOLD_TOKEN)
  2533.       Atmosphere->AA_Threshold = Parse_Float();
  2534.     END_CASE
  2535.  
  2536.     CASE (JITTER_TOKEN)
  2537.       Atmosphere->Jitter = Parse_Float();
  2538.     END_CASE
  2539.  
  2540.     CASE (ECCENTRICITY_TOKEN)
  2541.       Atmosphere->Eccentricity = Parse_Float();
  2542.     END_CASE
  2543.  
  2544.     CASE_COLOUR
  2545.       Parse_Colour(Atmosphere->Colour);
  2546.     END_CASE
  2547.  
  2548.     OTHERWISE
  2549.       UNGET
  2550.       EXIT
  2551.     END_CASE
  2552.   END_EXPECT
  2553.  
  2554.   Parse_End();
  2555.  
  2556.   return(Atmosphere);
  2557. }
  2558.  
  2559.  
  2560.  
  2561. /*****************************************************************************
  2562. *
  2563. * FUNCTION
  2564. *
  2565. * INPUT
  2566. *
  2567. * OUTPUT
  2568. *
  2569. * RETURNS
  2570. *
  2571. * AUTHOR
  2572. *
  2573. *   POV-Ray Team
  2574. *
  2575. * DESCRIPTION
  2576. *
  2577. * CHANGES
  2578. *
  2579. ******************************************************************************/
  2580.  
  2581. FOG *Parse_Fog()
  2582. {
  2583.   VECTOR Vector;
  2584.   MATRIX Matrix;
  2585.   TRANSFORM Trans;
  2586.   FOG *Fog;
  2587.  
  2588.   Parse_Begin();
  2589.  
  2590.   EXPECT
  2591.     CASE(FOG_ID_TOKEN)
  2592.       Fog = Copy_Fog ((FOG *) Token.Constant_Data);
  2593.       EXIT
  2594.     END_CASE
  2595.  
  2596.     OTHERWISE
  2597.       UNGET
  2598.       Fog = Create_Fog();
  2599.       EXIT
  2600.     END_CASE
  2601.   END_EXPECT
  2602.  
  2603.   EXPECT
  2604.     CASE_COLOUR
  2605.       Parse_Colour(Fog->Colour);
  2606.     END_CASE
  2607.  
  2608.     CASE (DISTANCE_TOKEN)
  2609.       Fog->Distance = Parse_Float();
  2610.     END_CASE
  2611.  
  2612.     CASE_FLOAT
  2613.       Warn(1.5, "Should use distance keyword.");
  2614.       Fog->Distance = Parse_Float();
  2615.     END_CASE
  2616.  
  2617.     CASE (FOG_TYPE_TOKEN)
  2618.       Fog->Type = (int)Parse_Float();
  2619.       if ((Fog->Type < ORIG_FOG) || (Fog->Type > FOG_TYPES))
  2620.       {
  2621.         Warn(0.0, "Unknown fog type.");
  2622.       }
  2623.     END_CASE
  2624.  
  2625.     CASE (FOG_ALT_TOKEN)
  2626.       Fog->Alt = Parse_Float();
  2627.     END_CASE
  2628.  
  2629.     CASE (FOG_OFFSET_TOKEN)
  2630.       Fog->Offset = Parse_Float();
  2631.     END_CASE
  2632.  
  2633.     CASE (TURB_DEPTH_TOKEN)
  2634.       Fog->Turb_Depth = Parse_Float();
  2635.     END_CASE
  2636.  
  2637.     CASE (UP_TOKEN)
  2638.       Parse_Vector(Fog->Up);
  2639.     END_CASE
  2640.  
  2641.     CASE (TURBULENCE_TOKEN)
  2642.       if (Fog->Turb == NULL)
  2643.       {
  2644.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2645.       }
  2646.       Parse_Vector_Float(Fog->Turb->Turbulence);
  2647.     END_CASE
  2648.  
  2649.     CASE (OCTAVES_TOKEN)
  2650.       if (Fog->Turb == NULL)
  2651.       {
  2652.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2653.       }
  2654.       Fog->Turb->Octaves = (int)Parse_Float();
  2655.       if(Fog->Turb->Octaves < 1)
  2656.         Fog->Turb->Octaves = 1;
  2657.       if(Fog->Turb->Octaves > 10)
  2658.          Fog->Turb->Octaves = 10;
  2659.     END_CASE
  2660.  
  2661.     CASE (OMEGA_TOKEN)
  2662.       if (Fog->Turb == NULL)
  2663.       {
  2664.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2665.       }
  2666.       Fog->Turb->Omega = Parse_Float();
  2667.     END_CASE
  2668.  
  2669.     CASE (LAMBDA_TOKEN)
  2670.       if (Fog->Turb == NULL)
  2671.       {
  2672.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2673.       }
  2674.       Fog->Turb->Lambda = Parse_Float();
  2675.     END_CASE
  2676.  
  2677.     CASE (ROTATE_TOKEN)
  2678.       Parse_Vector(Vector);
  2679.       Compute_Rotation_Transform(&Trans, Vector);
  2680.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2681.     END_CASE
  2682.  
  2683.     CASE (SCALE_TOKEN)
  2684.       Parse_Vector(Vector);
  2685.       Compute_Scaling_Transform(&Trans, Vector);
  2686.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2687.     END_CASE
  2688.  
  2689.     CASE (TRANSLATE_TOKEN)
  2690.       Parse_Vector(Vector);
  2691.       Warn(0.0, "A fog's up vector can't be translated.");
  2692. /*
  2693.       Compute_Translation_Transform(&Trans, Vector);
  2694.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2695. */
  2696.     END_CASE
  2697.  
  2698.     CASE (MATRIX_TOKEN)
  2699.       Parse_Matrix(Matrix);
  2700.       Compute_Matrix_Transform(&Trans, Matrix);
  2701.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2702.     END_CASE
  2703.  
  2704.     CASE (TRANSFORM_TOKEN)
  2705.       GET(TRANSFORM_ID_TOKEN)
  2706.       MTransDirection(Fog->Up, Fog->Up, (TRANSFORM *)Token.Constant_Data);
  2707.     END_CASE
  2708.  
  2709.     OTHERWISE
  2710.       UNGET
  2711.       EXIT
  2712.     END_CASE
  2713.   END_EXPECT
  2714.  
  2715.   Parse_End ();
  2716.  
  2717.   /* Make sure the up vector is normalized. */
  2718.  
  2719.   VNormalize(Fog->Up, Fog->Up);
  2720.  
  2721.   return(Fog);
  2722. }
  2723.  
  2724.  
  2725.  
  2726. /*****************************************************************************
  2727. *
  2728. * FUNCTION
  2729. *
  2730. *   Parse_Rainbow
  2731. *
  2732. * INPUT
  2733. *   
  2734. * OUTPUT
  2735. *   
  2736. * RETURNS
  2737. *   
  2738. * AUTHOR
  2739. *
  2740. *   Dieter Bayer
  2741. *   
  2742. * DESCRIPTION
  2743. *
  2744. *   -
  2745. *
  2746. * CHANGES
  2747. *
  2748. *   Jul 1994 : Creation.
  2749. *
  2750. *   Dec 1994 : Modified to work with multiple rainbows. [DB]
  2751. *
  2752. *   Apr 1995 : Added code for rainbow arcs. [DB]
  2753. *
  2754. ******************************************************************************/
  2755.  
  2756. RAINBOW *Parse_Rainbow()
  2757. {
  2758.   int Angle1, Angle2;
  2759.   DBL dot;
  2760.   RAINBOW *Rainbow;
  2761.  
  2762.   Angle1 = Angle2 = FALSE;
  2763.  
  2764.   Parse_Begin();
  2765.  
  2766.   EXPECT
  2767.     CASE(RAINBOW_ID_TOKEN)
  2768.       Rainbow = Copy_Rainbow ((RAINBOW *) Token.Constant_Data);
  2769.       EXIT
  2770.     END_CASE
  2771.  
  2772.     OTHERWISE
  2773.       UNGET
  2774.       Rainbow = Create_Rainbow();
  2775.       EXIT
  2776.     END_CASE
  2777.   END_EXPECT
  2778.  
  2779.   EXPECT
  2780.     CASE (ANGLE_TOKEN)
  2781.       Rainbow->Angle = Parse_Float();
  2782.     END_CASE
  2783.  
  2784.     CASE (DIRECTION_TOKEN)
  2785.       Parse_Vector(Rainbow->Antisolar_Vector);
  2786.     END_CASE
  2787.  
  2788.     CASE (COLOUR_MAP_TOKEN)
  2789.       Rainbow->Pigment = Create_Pigment();
  2790.       Rainbow->Pigment->Blend_Map = Parse_Colour_Map();
  2791.       Rainbow->Pigment->Type = GRADIENT_PATTERN;
  2792.       Make_Vector (Rainbow->Pigment->Vals.Gradient,1.0,0.0,0.0);
  2793.     END_CASE
  2794.  
  2795.     CASE (DISTANCE_TOKEN)
  2796.       Rainbow->Distance = Parse_Float();
  2797.     END_CASE
  2798.  
  2799.     CASE (JITTER_TOKEN)
  2800.       Rainbow->Jitter = Parse_Float();
  2801.     END_CASE
  2802.  
  2803.     CASE (WIDTH_TOKEN)
  2804.       Rainbow->Width = Parse_Float();
  2805.     END_CASE
  2806.  
  2807.     CASE (UP_TOKEN)
  2808.       Parse_Vector(Rainbow->Up_Vector);
  2809.     END_CASE
  2810.  
  2811.     CASE (FALLOFF_ANGLE_TOKEN)
  2812.       Angle1 = TRUE;
  2813.       Rainbow->Falloff_Angle = Parse_Float();
  2814.       if ((Rainbow->Falloff_Angle < 0.0) || (Rainbow->Falloff_Angle > 360.0))
  2815.       {
  2816.         Error("Illegal falloff angle in rainbow (Use value from 0 to 360 degrees).\n");
  2817.       }
  2818.       Rainbow->Falloff_Angle *= M_PI_360;
  2819.     END_CASE
  2820.  
  2821.     CASE (ARC_ANGLE_TOKEN)
  2822.       Angle2 = TRUE;
  2823.       Rainbow->Arc_Angle = Parse_Float();
  2824.       if ((Rainbow->Arc_Angle < 0.0) || (Rainbow->Arc_Angle > 360.0))
  2825.       {
  2826.         Error("Illegal arc angle in rainbow (Use value from 0 to 360 degrees).\n");
  2827.       }
  2828.       Rainbow->Arc_Angle *= M_PI_360;
  2829.     END_CASE
  2830.  
  2831.     OTHERWISE
  2832.       UNGET
  2833.       EXIT
  2834.     END_CASE
  2835.   END_EXPECT
  2836.  
  2837.   Parse_End();
  2838.  
  2839.   /* Setup falloff angle. */
  2840.  
  2841.   if (Angle2 && !Angle1)
  2842.   {
  2843.     Rainbow->Falloff_Angle = Rainbow->Arc_Angle;
  2844.   }
  2845.  
  2846.   /* Test if arc angle is greater or equal to falloff angle. */
  2847.  
  2848.   if (Rainbow->Arc_Angle < Rainbow->Falloff_Angle)
  2849.   {
  2850.     Error("Arc angle is smaller than falloff angle in rainbow.\n");
  2851.   }
  2852.  
  2853.   /* Get falloff region width.*/
  2854.  
  2855.   Rainbow->Falloff_Width = Rainbow->Arc_Angle - Rainbow->Falloff_Angle;
  2856.  
  2857.   /* Check for illegal vectors. */
  2858.  
  2859.   VDot(dot, Rainbow->Antisolar_Vector, Rainbow->Antisolar_Vector);
  2860.  
  2861.   if (fabs(dot) < EPSILON)
  2862.   {
  2863.     Error("Rainbow's direction vector is zero.\n");
  2864.   }
  2865.  
  2866.   VDot(dot, Rainbow->Up_Vector, Rainbow->Up_Vector);
  2867.  
  2868.   if (fabs(dot) < EPSILON)
  2869.   {
  2870.     Error("Rainbow's up vector is zero.\n");
  2871.   }
  2872.  
  2873.   VNormalizeEq(Rainbow->Antisolar_Vector);
  2874.   VNormalizeEq(Rainbow->Up_Vector);
  2875.  
  2876.   VDot(dot, Rainbow->Up_Vector, Rainbow->Antisolar_Vector);
  2877.  
  2878.   if (fabs(1.0 - fabs(dot)) < EPSILON)
  2879.   {
  2880.     Error("Rainbow's up and direction vector are co-linear.\n");
  2881.   }
  2882.  
  2883.   /* Make sure that up and antisolar vector are perpendicular. */
  2884.  
  2885.   VCross(Rainbow->Right_Vector, Rainbow->Up_Vector, Rainbow->Antisolar_Vector);
  2886.  
  2887.   VCross(Rainbow->Up_Vector, Rainbow->Antisolar_Vector, Rainbow->Right_Vector);
  2888.  
  2889.   VNormalizeEq(Rainbow->Up_Vector);
  2890.   VNormalizeEq(Rainbow->Right_Vector);
  2891.  
  2892.   /* Adjust rainbow angle and width. */
  2893.  
  2894.   Rainbow->Angle -= 0.5 * Rainbow->Width;
  2895.  
  2896.   Rainbow->Angle *= M_PI_180;
  2897.   Rainbow->Width *= M_PI_180;
  2898.  
  2899.   return(Rainbow);
  2900. }
  2901.  
  2902.  
  2903.  
  2904. /*****************************************************************************
  2905. *
  2906. * FUNCTION
  2907. *
  2908. *   Parse_Skysphere
  2909. *
  2910. * INPUT
  2911. *   
  2912. * OUTPUT
  2913. *   
  2914. * RETURNS
  2915. *   
  2916. * AUTHOR
  2917. *
  2918. *   Dieter Bayer
  2919. *   
  2920. * DESCRIPTION
  2921. *
  2922. *   -
  2923. *
  2924. * CHANGES
  2925. *
  2926. *   Jul 1994 : Creation.
  2927. *
  2928. *   Dec 1994 : Modified to work with multiple skyspheres. [DB]
  2929. *
  2930. ******************************************************************************/
  2931.  
  2932. SKYSPHERE *Parse_Skysphere()
  2933. {
  2934.   VECTOR Local_Vector;
  2935.   MATRIX Local_Matrix;
  2936.   TRANSFORM Local_Trans;
  2937.   SKYSPHERE *Skysphere;
  2938.  
  2939.   Parse_Begin();
  2940.  
  2941.   EXPECT
  2942.     CASE(SKYSPHERE_ID_TOKEN)
  2943.       Skysphere = Copy_Skysphere((SKYSPHERE *)Token.Constant_Data);
  2944.       EXIT
  2945.     END_CASE
  2946.  
  2947.     OTHERWISE
  2948.       UNGET
  2949.       Skysphere = Create_Skysphere();
  2950.       EXIT
  2951.     END_CASE
  2952.   END_EXPECT
  2953.  
  2954.   EXPECT
  2955.     CASE (PIGMENT_TOKEN)
  2956.       Skysphere->Count++;
  2957.       Skysphere->Pigments = POV_REALLOC(Skysphere->Pigments, Skysphere->Count*sizeof(SKYSPHERE *), "sky-sphere pigment");
  2958.       Skysphere->Pigments[Skysphere->Count-1] = Create_Pigment();
  2959.       Parse_Begin();
  2960.       Parse_Pigment(&(Skysphere->Pigments[Skysphere->Count-1]));
  2961.       Parse_End();
  2962.     END_CASE
  2963.  
  2964.     CASE (TRANSLATE_TOKEN)
  2965.       Parse_Vector (Local_Vector);
  2966.       Translate_Skysphere(Skysphere, Local_Vector);
  2967.     END_CASE
  2968.  
  2969.     CASE (ROTATE_TOKEN)
  2970.       Parse_Vector (Local_Vector);
  2971.       Rotate_Skysphere(Skysphere, Local_Vector);
  2972.     END_CASE
  2973.  
  2974.     CASE (SCALE_TOKEN)
  2975.       Parse_Scale_Vector (Local_Vector);
  2976.       Scale_Skysphere(Skysphere, Local_Vector);
  2977.     END_CASE
  2978.  
  2979.     CASE (MATRIX_TOKEN)
  2980.       Parse_Matrix(Local_Matrix);
  2981.       Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  2982.       Transform_Skysphere(Skysphere, &Local_Trans);
  2983.     END_CASE
  2984.  
  2985.     CASE (TRANSFORM_TOKEN)
  2986.       GET(TRANSFORM_ID_TOKEN)
  2987.       Transform_Skysphere(Skysphere, (TRANSFORM *)Token.Constant_Data);
  2988.     END_CASE
  2989.  
  2990.     OTHERWISE
  2991.       UNGET
  2992.       EXIT
  2993.     END_CASE
  2994.   END_EXPECT
  2995.  
  2996.   Parse_End();
  2997.   
  2998.   if (Skysphere->Count==0)
  2999.   {
  3000.     Error("Empty sky_sphere statement.");
  3001.   }
  3002.  
  3003.   return(Skysphere);
  3004. }
  3005.  
  3006. /*****************************************************************************
  3007. *
  3008. * FUNCTION      : Check_BH_Parameters
  3009. *
  3010. * ARGUMENTS     : bh - pointer to Black_Hole
  3011. *
  3012. * AUTHOR        : CJC [7/95]
  3013. *
  3014. * DESCRIPTION   : Applies sanity checks to the parameters of a black hole.
  3015. *
  3016. * CHANGES
  3017. *
  3018. ******************************************************************************/
  3019.  
  3020. static void Check_BH_Parameters (bh)
  3021. BLACK_HOLE *bh;
  3022. {
  3023.   if (bh->Repeat == FALSE) return ;
  3024.  
  3025.   if (bh->Repeat_Vector [X] > 0.0)
  3026.   {
  3027.     if (bh->Center [X] < bh->Radius)
  3028.       bh->Center [X] = bh->Radius ;
  3029.     if (bh->Repeat_Vector [X] < bh->Center [X] + bh->Radius + bh->Uncertainty_Vector [X])
  3030.     {
  3031.       bh->Repeat_Vector [X] = bh->Center [X] + bh->Radius + bh->Uncertainty_Vector [X] ;
  3032.       Warning (0.0, "Black Hole repeat vector X too small ; increased to %g\n", bh->Repeat_Vector [X]) ;
  3033.     } 
  3034.     if (bh->Repeat_Vector [X] < Small_Tolerance)
  3035.     {
  3036.       Warning (0.0,"Black Hole repeat vector X is less than %f ; ignored\n", (float) Small_Tolerance) ;
  3037.       bh->Repeat_Vector [X] = 0.0 ;
  3038.     }
  3039.   }
  3040.  
  3041.   if (bh->Repeat_Vector [Y] > 0.0)
  3042.   {
  3043.     if (bh->Center [Y] < bh->Radius)
  3044.       bh->Center [Y] = bh->Radius ;
  3045.     if (bh->Repeat_Vector [Y] < bh->Center [Y] + bh->Radius + bh->Uncertainty_Vector [Y])
  3046.     {
  3047.       bh->Repeat_Vector [Y] = bh->Center [Y] + bh->Radius + bh->Uncertainty_Vector [Y] ;
  3048.       Warning (0.0, "Black Hole repeat vector Y too small ; increased to %g\n", bh->Repeat_Vector [Y]) ;
  3049.     } 
  3050.     if (bh->Repeat_Vector [Y] < Small_Tolerance)
  3051.     {
  3052.       Warning (0.0, "Black Hole repeat vector Y is less than %f ; ignored\n", (float) Small_Tolerance) ;
  3053.       bh->Repeat_Vector [Y] = 0.0 ;
  3054.     } 
  3055.   }
  3056.  
  3057.   if (bh->Repeat_Vector [Z] > 0.0)
  3058.   {
  3059.     if (bh->Center [Z] < bh->Radius)
  3060.       bh->Center [Z] = bh->Radius ;
  3061.     if (bh->Repeat_Vector [Z] < bh->Center [Z] + bh->Radius + bh->Uncertainty_Vector [Z])
  3062.     {
  3063.       bh->Repeat_Vector [Z] = bh->Center [Z] + bh->Radius + bh->Uncertainty_Vector [Z] ;
  3064.       Warning (0.0, "Black Hole repeat vector Z too small ; increased to %g\n", bh->Repeat_Vector [Z]) ;
  3065.     } 
  3066.     if (bh->Repeat_Vector [Z] < Small_Tolerance)
  3067.     {
  3068.       Warning (0.0, "Black Hole repeat vector Z is less than %f ; ignored\n", (float) Small_Tolerance) ;
  3069.       bh->Repeat_Vector [Z] = 0.0 ;
  3070.     }
  3071.   }
  3072. }
  3073.  
  3074. /*****************************************************************************
  3075. *
  3076. * FUNCTION
  3077. *
  3078. *   Check_Turb
  3079. *
  3080. * INPUT
  3081. *
  3082. *   Warps_Ptr : Address where the root warp of a warp list
  3083. *   is stored.
  3084. *   
  3085. * OUTPUT
  3086. *
  3087. *   Warps_Ptr : If *Warps_Ptr is NULL, a classic turb warp
  3088. *   is created and a pointer to it is stored
  3089. *   
  3090. * RETURNS
  3091. *
  3092. *   A pointer to the last warp in the chain which is guarenteed
  3093. *   to be a classic turb.
  3094. *   
  3095. * AUTHOR
  3096. *
  3097. *   CEY [2/95]
  3098. *   
  3099. * DESCRIPTION   : This routine is called when a classic outside-the-warp
  3100. *  turbulence parameter is parsed.  One and only one classic turb may exist 
  3101. *  in a warp chain.  If there is one, it must be the last.  This routine 
  3102. *  traverses the warp chain and looks at the last link.  If it is not a 
  3103. *  classic turb then it adds one to the end and returns a pointer to it.
  3104. *  If the chain is empty, it creates a single link chain consisting of a 
  3105. *  classic turb link.  Future warp links get added ahead of the chain so
  3106. *  that any classic turb link is always last.
  3107. *
  3108. * CHANGES
  3109. *
  3110. ******************************************************************************/
  3111.  
  3112. static TURB *Check_Turb (Warps_Ptr)
  3113. WARP **Warps_Ptr;
  3114. {
  3115.   WARP *Temp=*Warps_Ptr;
  3116.   
  3117.   if (Temp == NULL)
  3118.   {
  3119.     *Warps_Ptr = Temp = Create_Warp(CLASSIC_TURB_WARP);
  3120.   }
  3121.   else
  3122.   {
  3123.     while (Temp->Next_Warp != NULL)
  3124.     {
  3125.       Temp=Temp->Next_Warp;
  3126.     }
  3127.   
  3128.     if (Temp->Warp_Type != CLASSIC_TURB_WARP)
  3129.     {
  3130.       Temp->Next_Warp=Create_Warp(CLASSIC_TURB_WARP);
  3131.       Temp=Temp->Next_Warp;
  3132.     }
  3133.   }
  3134.   return((TURB *)Temp);
  3135. }
  3136.  
  3137.  
  3138.  
  3139. /*****************************************************************************
  3140. *
  3141. * FUNCTION
  3142. *
  3143. * INPUT
  3144. *
  3145. * OUTPUT
  3146. *
  3147. * RETURNS
  3148. *
  3149. * AUTHOR
  3150. *
  3151. *   POV-Ray Team
  3152. *   
  3153. * DESCRIPTION
  3154. *
  3155. * CHANGES
  3156. *
  3157. ******************************************************************************/
  3158.  
  3159. static void Parse_Warp (Warp_Ptr)
  3160. WARP **Warp_Ptr;
  3161. {
  3162.   WARP *New = NULL;
  3163.   TURB *Turb;
  3164.   REPEAT *Repeat;
  3165.   BLACK_HOLE *Black_Hole;
  3166.   VECTOR Local_Vector;
  3167.  
  3168.   Parse_Begin();
  3169.  
  3170.   EXPECT
  3171.     CASE(TURBULENCE_TOKEN)
  3172.       New=Create_Warp(EXTRA_TURB_WARP);
  3173.       Turb=(TURB *)New;
  3174.       Parse_Vector(Turb->Turbulence);
  3175.       EXPECT
  3176.         CASE(OCTAVES_TOKEN)
  3177.           Turb->Octaves = (int)Parse_Float();
  3178.           if(Turb->Octaves < 1)
  3179.              Turb->Octaves = 1;
  3180.           if(Turb->Octaves > 10)  /* Avoid DOMAIN errors */
  3181.              Turb->Octaves = 10;
  3182.         END_CASE
  3183.  
  3184.         CASE (OMEGA_TOKEN)
  3185.           Turb->Omega = Parse_Float();
  3186.         END_CASE
  3187.  
  3188.         CASE (LAMBDA_TOKEN)
  3189.           Turb->Lambda = Parse_Float();
  3190.         END_CASE
  3191.         
  3192.         OTHERWISE
  3193.           UNGET
  3194.           EXIT
  3195.         END_CASE
  3196.       END_EXPECT
  3197.       EXIT
  3198.     END_CASE
  3199.  
  3200.     CASE(REPEAT_TOKEN)
  3201.       New=Create_Warp(REPEAT_WARP);
  3202.       Repeat=(REPEAT *)New;
  3203.       Parse_Vector(Local_Vector);
  3204.       Repeat->Axis=-1;
  3205.       if (Local_Vector[X]!=0.0) 
  3206.         Repeat->Axis=X;
  3207.       if (Local_Vector[Y]!=0.0)
  3208.         if (Repeat->Axis < X)
  3209.           Repeat->Axis=Y;
  3210.         else 
  3211.           Error("Can only repeat along 1 axis.");
  3212.       if (Local_Vector[Z]!=0.0)
  3213.         if (Repeat->Axis < X)
  3214.           Repeat->Axis=Z;
  3215.         else
  3216.           Error("Can only repeat along 1 axis.");
  3217.       if (Repeat->Axis < X)
  3218.         Error("No axis specified in repeat.");
  3219.       Repeat->Width=Local_Vector[Repeat->Axis];
  3220.          
  3221.       EXPECT
  3222.         CASE(OFFSET_TOKEN)
  3223.           Parse_Vector(Repeat->Offset);
  3224.         END_CASE
  3225.         
  3226.         CASE(FLIP_TOKEN)
  3227.           Parse_Vector(Repeat->Flip);
  3228.           if (Repeat->Flip[X]!=0.0) Repeat->Flip[X]=-1.0; else Repeat->Flip[X]=1.0;
  3229.           if (Repeat->Flip[Y]!=0.0) Repeat->Flip[Y]=-1.0; else Repeat->Flip[Y]=1.0;
  3230.           if (Repeat->Flip[Z]!=0.0) Repeat->Flip[Z]=-1.0; else Repeat->Flip[Z]=1.0;
  3231.         END_CASE
  3232.         
  3233.         OTHERWISE
  3234.           UNGET
  3235.           EXIT
  3236.         END_CASE
  3237.       END_EXPECT
  3238.       EXIT
  3239.     END_CASE
  3240.     
  3241.     CASE(BLACK_HOLE_TOKEN)
  3242.       New = Create_Warp(BLACK_HOLE_WARP) ;
  3243.       Black_Hole = (BLACK_HOLE *) New ;
  3244.       Parse_Vector (Local_Vector) ;
  3245.       Assign_Vector (Black_Hole->Center, Local_Vector) ;
  3246.       Parse_Comma () ;
  3247.       Black_Hole->Radius = Parse_Float () ;
  3248.       Black_Hole->Radius_Squared = Black_Hole->Radius * Black_Hole->Radius ;
  3249.       Black_Hole->Inverse_Radius = 1.0 / Black_Hole->Radius;
  3250.       Black_Hole->Strength = 1.0 ;
  3251.       Black_Hole->Power = 2.0 ;
  3252.       Black_Hole->Inverted = FALSE ;
  3253.       Black_Hole->Type = 0 ;
  3254.  
  3255.       EXPECT
  3256.         CASE(STRENGTH_TOKEN)
  3257.           Black_Hole->Strength = Parse_Float () ;
  3258.         END_CASE
  3259.  
  3260.         CASE(FALLOFF_TOKEN)
  3261.           Black_Hole->Power = Parse_Float () ;
  3262.         END_CASE
  3263.  
  3264.         CASE(INVERSE_TOKEN)
  3265.           Black_Hole->Inverted = TRUE ;
  3266.         END_CASE
  3267.  
  3268.         CASE(TYPE_TOKEN)
  3269.           Black_Hole->Type = (int) Parse_Float () ;
  3270.         END_CASE
  3271.  
  3272.         CASE(REPEAT_TOKEN)
  3273.           Parse_Vector (Black_Hole->Repeat_Vector) ;
  3274.           Black_Hole->Repeat = TRUE ;
  3275.           Check_BH_Parameters (Black_Hole) ;
  3276.         END_CASE
  3277.  
  3278.         CASE(TURBULENCE_TOKEN)
  3279.           Parse_Vector (Black_Hole->Uncertainty_Vector) ;
  3280.           Black_Hole->Uncertain = TRUE ;
  3281.           Check_BH_Parameters (Black_Hole) ;
  3282.         END_CASE
  3283.  
  3284.         OTHERWISE
  3285.           UNGET
  3286.           EXIT
  3287.         END_CASE
  3288.       END_EXPECT
  3289.       EXIT
  3290.     END_CASE
  3291.       
  3292.     CASE(SPIRAL_TOKEN)
  3293.       Error("Spiral warp not yet implemented.");
  3294.     END_CASE
  3295.  
  3296.     OTHERWISE
  3297.       Parse_Error_Str ("warp type");
  3298.     END_CASE
  3299.   END_EXPECT
  3300.  
  3301.   if (New==NULL)
  3302.   {
  3303.      Error("Empty warp statement.");
  3304.   }
  3305.   
  3306.   New->Next_Warp=*Warp_Ptr;
  3307.   *Warp_Ptr=New;
  3308.  
  3309.   Parse_End();
  3310. }
  3311.